clone

a daily shikaku puzzle for phones: one seeded puzzle per date, solved by dragging rectangles

Initial public release

Dami committed ddd2607
commit
ddd26075f4b2f684521e64ea72cc54044eb4d3b0
author
Dami <dami.etoile@gmail.com>
71 files changed, +8240 -0
A.github/skills/README.md20+
A.github/skills/deno-deploy/SKILL.md567++++++++++++++
A.github/skills/deno-deploy/references/AUTHENTICATION.md163++++
A.github/skills/deno-deploy/references/DATABASES.md152++++
A.github/skills/deno-deploy/references/DENO_KV.md147++++
A.github/skills/deno-deploy/references/DOMAINS.md88++
A.github/skills/deno-deploy/references/FRAMEWORKS.md197+++++
A.github/skills/deno-deploy/references/ORGANIZATIONS.md79++
A.github/skills/deno-deploy/references/RUNTIME.md90++
A.github/skills/deno-deploy/references/TROUBLESHOOTING.md174++++
A.github/skills/deno-expert/SKILL.md255++++++
A.github/skills/deno-frontend/SKILL.md886+++++++++++++++++++++
A.github/skills/deno-guidance/SKILL.md239++++++
A.github/skills/deno-project-templates/SKILL.md258++++++
A.github/skills/deno-project-templates/assets/api-server/deno.json9+
A.github/skills/deno-project-templates/assets/api-server/main.ts20+
A.github/skills/deno-project-templates/assets/cli-tool/deno.json13+
A.github/skills/deno-project-templates/assets/cli-tool/main.ts28+
A.github/skills/deno-project-templates/assets/fresh-app/README.md33+
A.github/skills/deno-project-templates/assets/library/deno.json10+
A.github/skills/deno-project-templates/assets/library/mod.ts21+
A.github/skills/deno-project-templates/assets/library/mod_test.ts6+
A.github/skills/deno-sandbox/SKILL.md395++++++++++
A.gitignore15+
AREADME.md17+
Aassets/styles.css788+++++++++++++++++++
Aclient.ts2+
Acomponents/Button.tsx17+
Adata/puzzles/2026-04-16.json20+
Adeno.json63++
Adeno.lock1243++++++++++++++++++++++++++++++
Aislands/Counter.tsx16+
Aislands/ShikakuGame.tsx414++++++++++
Alib/date/daily.ts30+
Alib/shikaku/catalog.ts14+
Alib/shikaku/clue_symbol.ts15+
Alib/shikaku/clue_tone.ts3+
Alib/shikaku/engine.ts111+++
Alib/shikaku/generator.ts410++++++++++
Alib/shikaku/interaction.ts39+
Alib/shikaku/play_state.ts9+
Alib/shikaku/types.ts150++++
Alib/site/brand.ts10+
Alib/storage/local_progress.ts58+
Amain.ts30+
Aroutes/_app.tsx52+
Aroutes/api/[name].tsx10+
Aroutes/api/puzzles/[date].ts11+
Aroutes/daily/[date].tsx69++
Aroutes/daily/index.tsx13+
Aroutes/index.tsx58+
Astatic/apple-touch-icon.pngbin
Astatic/favicon.icobin
Astatic/icon-192.pngbin
Astatic/icon-512.pngbin
Astatic/icon.svg77++
Astatic/logo.svg19+
Astatic/site.webmanifest30+
Atests/lib/date/daily_test.ts43+
Atests/lib/shikaku/catalog_test.ts26+
Atests/lib/shikaku/clue_symbol_test.ts16+
Atests/lib/shikaku/clue_tone_test.ts8+
Atests/lib/shikaku/engine_test.ts161++++
Atests/lib/shikaku/generator_test.ts84++
Atests/lib/shikaku/interaction_test.ts33+
Atests/lib/shikaku/play_state_test.ts16+
Atests/lib/shikaku/types_test.ts44+
Atests/lib/site/brand_test.ts21+
Atests/lib/storage/local_progress_test.ts110+++
Autils.ts9+
Avite.config.ts6+
A .github/skills/README.md +20 -0
A .github/skills/deno-deploy/SKILL.md +567 -0
@@ -0,0 +1,567 @@
1+---2+name: deno-deploy3+description: Use when deploying Deno apps to production, asking about Deno Deploy, or working with `deno deploy` CLI commands. Covers deployment workflows, environment variables, KV database access, custom domains, the --tunnel flag for local development, and the `deno deploy` command reference.4+license: MIT5+metadata:6+ author: denoland7+ version: "1.5"8+---9+10+# Deno Deploy11+12+This skill provides guidance for deploying applications to Deno Deploy.13+14+## Scope Boundaries15+16+This skill applies **only** to Deno Deploy questions. Follow these rules:17+18+- If the user asks about **AWS Lambda, Vercel, Netlify, Google Cloud Run, Docker, Kubernetes, or any other deployment platform**, answer using that platform directly. Do not mention Deno Deploy at all — not as an alternative, not as a comparison, not as a suggestion.19+- If the user asks about **running a local Deno script** (not deploying), answer the local question directly. Do not mention Deno Deploy, deployment, or the `--tunnel` flag.20+- Do not include `deno deploy` commands, Deno KV, or Deno Deploy environment variable configuration in responses about other platforms or local-only scripts.21+- Only discuss Deno Deploy when the user explicitly asks about Deno Deploy or deploying a Deno application to production.22+23+## Important: Use `deno deploy`, NOT `deployctl`24+25+**Always use the `deno deploy` command.** Do NOT use `deployctl`.26+27+- `deployctl` is for Deno Deploy Classic (deprecated)28+- `deno deploy` is the modern, integrated command built into the Deno CLI29+- **Requires Deno >= 2.4.2** - the `deno deploy` subcommand was introduced in Deno 2.430+31+## When Unsure About CLI Flags32+33+**Always run `--help` before guessing at flags.** The `deno deploy` subcommand has many flags, and they change between versions. When you're unsure what a command accepts:34+35+```bash36+# See all subcommands37+deno deploy --help38+39+# See flags for a specific subcommand40+deno deploy create --help41+deno deploy env --help42+deno deploy database --help43+```44+45+This takes seconds and prevents repeated trial-and-error failures. Never assume a flag exists — check first.46+47+## Deployment Workflow48+49+**Always show the core deploy command first** — then explain diagnostic steps. When a user asks "how do I deploy?", lead with the actual command (`deno deploy --prod`) before covering pre-flight checks and configuration.50+51+### Step 1: Locate the App Directory52+53+Before running any deploy commands, find where the Deno app is located:54+55+```bash56+# Check if deno.json exists in current directory57+if [ -f "deno.json" ] || [ -f "deno.jsonc" ]; then58+ echo "APP_DIR: $(pwd)"59+else60+ # Look for deno.json in immediate subdirectories61+ find . -maxdepth 2 -name "deno.json" -o -name "deno.jsonc" 2>/dev/null | head -562+fi63+```64+65+All deploy commands must run from the app directory.66+67+### Step 2: Pre-Flight Checks68+69+Check Deno version and existing configuration:70+71+```bash72+# Check Deno version (must be >= 2.4.2)73+deno --version | head -174+75+# Check for existing deploy config76+grep -E '"org"|"app"' deno.json deno.jsonc 2>/dev/null || echo "NO_DEPLOY_CONFIG"77+```78+79+### Step 3: Check for Startup Dependencies80+81+Before deploying, check if the app connects to a database or external service at startup (e.g., top-level `await initDb()` in `main.ts`). If it does, the deploy will fail during warmup because the database doesn't exist yet.82+83+**If the app has startup database dependencies, follow this order:**84+85+1. **Create the app with `--no-wait`** so a warmup failure doesn't block you:86+ ```bash87+ deno deploy create \88+ --org <ORG_NAME> --app <APP_NAME> \89+ --source local --runtime-mode dynamic --entrypoint main.ts \90+ --build-timeout 5 --build-memory-limit 1024 --region us \91+ --no-wait92+ ```93+94+2. **Provision and assign the database:**95+ ```bash96+ deno deploy database provision my-db --kind prisma --region us-east-197+ deno deploy database assign my-db --app <APP_NAME>98+ ```99+100+3. **Redeploy** (now the database exists, warmup will succeed):101+ ```bash102+ deno deploy --prod103+ ```104+105+If the app has no startup dependencies, skip this step and deploy normally below.106+107+### Step 4: Deploy Based on Configuration108+109+**If `deploy.org` AND `deploy.app` exist in deno.json:**110+```bash111+# Build if needed (Fresh, Astro, etc.)112+deno task build113+114+# Deploy to production115+deno deploy --prod116+```117+118+**If NO deploy config exists:**119+120+**Apps must be created before they can be deployed to.** You cannot run `deno deploy --prod` until an app exists.121+122+**IMPORTANT: Ask the user first** - Do they have an existing app on Deno Deploy, or do they need to create a new one?123+124+**If they have an existing app**, add the config directly to deno.json:125+```json126+{127+ "deploy": {128+ "org": "<ORG_NAME>",129+ "app": "<APP_NAME>"130+ }131+}132+```133+The org name is in the Deno Deploy console URL (e.g., `console.deno.com/your-org-name`). Once this config is in place, subsequent deploys just need `deno deploy --prod`.134+135+**If they need to create a new app:**136+137+The CLI needs an organization name. Find it at https://console.deno.com - the org is in the URL path (e.g., `console.deno.com/your-org-name`).138+139+**Interactive creation** (opens a browser — only works when a human is at the keyboard):140+```bash141+deno deploy create --org <ORG_NAME>142+# A browser window opens - complete the app creation there143+```144+145+**Non-interactive creation** (use when an AI agent is performing the deploy, or in CI/CD):146+```bash147+deno deploy create \148+ --org <ORG_NAME> \149+ --app <APP_NAME> \150+ --source local \151+ --runtime-mode dynamic \152+ --entrypoint main.ts \153+ --build-timeout 5 \154+ --build-memory-limit 1024 \155+ --region us156+```157+158+The create command also does the initial deploy. After it completes, `deno.json` is updated with `deploy.org` and `deploy.app` automatically. From that point on, subsequent deploys only need:159+```bash160+deno deploy --prod161+```162+163+After completion, verify the config was saved:164+```bash165+grep -E '"org"|"app"' deno.json166+```167+168+**When an AI agent is performing the deployment**, always use the non-interactive flow with explicit flags. The interactive flow requires browser windows and terminal prompts that agents cannot navigate.169+170+## Core Commands171+172+### Production Deployment173+174+```bash175+deno deploy --prod176+```177+178+### Preview Deployment179+180+```bash181+deno deploy182+```183+184+Preview deployments create a unique URL for testing without affecting production.185+186+### Targeting Specific Apps187+188+```bash189+deno deploy --org my-org --app my-app --prod190+```191+192+### Configuring an Entrypoint193+194+Set the entrypoint in your `deno.json` (this is used by `deno deploy create` during app creation):195+196+```json197+{198+ "deploy": {199+ "entrypoint": "main.ts"200+ }201+}202+```203+204+Note: `--entrypoint` is a flag on `deno deploy create`, not on `deno deploy` itself.205+206+### Additional Flags207+208+These flags are available on `deno deploy create` (and apply during the initial deploy):209+210+| Flag | Purpose |211+|------|---------|212+| `--allow-node-modules` | Include node_modules directory in upload |213+| `--no-wait` | Skip waiting for the build to complete |214+215+## Creating Apps (Non-Interactive Reference)216+217+When any flag beyond `--org` is provided, `deno deploy create` runs in non-interactive mode — all required flags must be specified. This is the recommended approach for AI agents and CI/CD pipelines.218+219+### Required Flags220+221+| Flag | Description |222+|------|-------------|223+| `--org <name>` | Organization name |224+| `--app <name>` | Application name (becomes your URL: `<app>.deno.dev`) |225+| `--source <local\|github>` | Deploy from local files or a GitHub repo |226+| `--build-timeout <minutes>` | Build timeout: 5, 10, 15, 20, 25, or 30 |227+| `--build-memory-limit <MB>` | Memory limit: 1024, 2048, 3072, or 4096 |228+| `--region <region>` | Deployment region: us, eu, or global |229+230+### GitHub Source Flags231+232+When using `--source github`, you also need:233+234+| Flag | Description |235+|------|-------------|236+| `--owner <name>` | GitHub repository owner |237+| `--repo <name>` | GitHub repository name |238+239+### Build Configuration Flags240+241+| Flag | Description |242+|------|-------------|243+| `--app-directory <path>` | Path to app directory (for monorepos) |244+| `--framework-preset <preset>` | Framework preset (see [Frameworks](references/FRAMEWORKS.md)) |245+| `--install-command <cmd>` | Custom install command |246+| `--build-command <cmd>` | Custom build command |247+| `--pre-deploy-command <cmd>` | Command to run before deploy |248+| `--do-not-use-detected-build-config` | Skip auto-detection of framework config |249+250+The CLI auto-detects your framework and build configuration. If a framework is detected, you can skip `--install-command`, `--build-command`, `--pre-deploy-command`, and `--runtime-mode` — they'll be inferred from the preset. Use `--do-not-use-detected-build-config` to override detection. **When using this flag, all three build commands (`--install-command`, `--build-command`, `--pre-deploy-command`) plus `--runtime-mode` become required** — omitting any of them causes exit code 2.251+252+### Runtime Mode Flags253+254+You must pick a runtime mode with `--runtime-mode <dynamic|static>` (unless a framework preset handles it).255+256+**Dynamic mode** (for apps with a server):257+258+| Flag | Description |259+|------|-------------|260+| `--entrypoint <path>` | Entry file (required for dynamic mode) |261+| `--arguments <args>` | Arguments passed to entrypoint (repeatable) |262+| `--working-directory <cwd>` | Working directory for the process |263+264+**Static mode** (for static sites):265+266+| Flag | Description |267+|------|-------------|268+| `--static-dir <dir>` | Directory to serve static files from (required) |269+| `--single-page-app` | Serve index.html for routes that don't match a file |270+271+### Other Flags272+273+| Flag | Description |274+|------|-------------|275+| `--dry-run` | Validate everything without actually creating the app |276+| `--no-wait` | Don't wait for the build to complete |277+| `--allow-node-modules` | Include node_modules in the upload |278+279+### Examples280+281+**Simple Deno server:**282+```bash283+deno deploy create \284+ --org my-org --app my-api \285+ --source local \286+ --runtime-mode dynamic --entrypoint main.ts \287+ --build-timeout 5 --build-memory-limit 1024 --region us288+```289+290+**Fresh app (framework auto-detected):**291+```bash292+deno deploy create \293+ --org my-org --app my-fresh-app \294+ --source local \295+ --build-timeout 5 --build-memory-limit 1024 --region us296+```297+298+**Next.js from GitHub:**299+```bash300+deno deploy create \301+ --org my-org --app my-next-app \302+ --source github --owner my-github-user --repo my-next-repo \303+ --framework-preset Next \304+ --build-timeout 15 --build-memory-limit 2048 --region us \305+ --allow-node-modules306+```307+308+**Static site:**309+```bash310+deno deploy create \311+ --org my-org --app my-static-site \312+ --source local \313+ --runtime-mode static --static-dir dist --single-page-app \314+ --build-command "deno task build" \315+ --build-timeout 5 --build-memory-limit 1024 --region us316+```317+318+## Environment Variables319+320+### Contexts321+322+Deno Deploy has three "contexts" - logical environments where your code runs, each with its own set of variables:323+324+| Context | Purpose |325+|---------|---------|326+| **Production** | Live traffic on your production URL |327+| **Development** | Preview deployments and branch URLs |328+| **Build** | Only available during the build process |329+330+You can set different values for the same variable in each context. For example, you might use a test database URL in Development and the real one in Production.331+332+### Predefined Variables333+334+These are automatically available in your code:335+336+| Variable | Description |337+|----------|-------------|338+| `DENO_DEPLOY` | Always `1` when running on Deno Deploy |339+| `DENO_DEPLOYMENT_ID` | Unique ID for the current deployment |340+| `DENO_DEPLOY_ORG_ID` | Your organization's ID |341+| `DENO_DEPLOY_APP_ID` | Your application's ID |342+| `CI` | Set to `1` during builds only |343+344+### Accessing Variables in Code345+346+```typescript347+const dbUrl = Deno.env.get("DATABASE_URL");348+const isDenoDeploy = Deno.env.get("DENO_DEPLOY") === "1";349+```350+351+### Managing Variables via CLI352+353+```bash354+# Add a plain text variable355+deno deploy env add DATABASE_URL "postgres://..."356+357+# Add a secret variable (hidden after creation, only readable in code)358+deno deploy env add API_KEY "sk-..." --secret359+360+# List all variables361+deno deploy env list362+363+# Update just the value (keeps contexts and secret status)364+deno deploy env update-value DATABASE_URL "postgres://new-url..."365+366+# Update which contexts a variable applies to367+deno deploy env update-contexts DATABASE_URL production development368+369+# Delete a variable370+deno deploy env delete DATABASE_URL371+372+# Load from .env file (all values treated as secrets by default)373+deno deploy env load .env.production374+375+# Load from .env file, marking specific keys as non-secrets376+deno deploy env load .env.production --non-secrets PUBLIC_URL APP_NAME377+```378+379+### Variable Types380+381+- **Plain text** - Visible in the dashboard, good for feature flags and non-sensitive config382+- **Secrets** - Hidden after creation, only readable in your code, use for API keys and credentials383+384+### Limits385+386+- Key names: max 128 bytes387+- Values: max 16 KB388+- Keys cannot start with `DENO_`, `LD_`, or `OTEL_`389+390+## Viewing Logs391+392+```bash393+# Stream live logs394+deno deploy logs395+396+# Filter by date range397+deno deploy logs --start 2026-01-15 --end 2026-01-16398+```399+400+## Databases & Storage401+402+Deno Deploy provides built-in database support with **automatic environment isolation**. Each environment (production, preview, branch) gets its own isolated database automatically.403+404+### Available Options405+406+| Engine | Use Case |407+|--------|----------|408+| **Deno KV** | Key-value storage, simple data, counters, sessions |409+| **PostgreSQL** | Relational data, complex queries, existing Postgres apps |410+411+### Deno KV Quick Start412+413+No configuration needed - just use the built-in API:414+415+```typescript416+const kv = await Deno.openKv();417+418+// Store data419+await kv.set(["users", "alice"], { name: "Alice", role: "admin" });420+421+// Retrieve data422+const user = await kv.get(["users", "alice"]);423+console.log(user.value); // { name: "Alice", role: "admin" }424+425+// List by prefix426+for await (const entry of kv.list({ prefix: ["users"] })) {427+ console.log(entry.key, entry.value);428+}429+```430+431+Deno Deploy automatically connects to the correct database based on your environment.432+433+### PostgreSQL434+435+For PostgreSQL, Deno Deploy injects environment variables (`DATABASE_URL`, `PGHOST`, etc.) that most libraries detect automatically:436+437+```typescript438+// Recommended: npm:pg (best PostgreSQL driver for Deno Deploy)439+import pg from "npm:pg";440+const pool = new pg.Pool(); // Reads DATABASE_URL from environment automatically441+```442+443+### Provisioning444+445+Use the `deno deploy database` command to provision and manage databases:446+447+```bash448+# Provision a Deno KV database449+deno deploy database provision my-database --kind denokv450+451+# Provision a Prisma PostgreSQL database452+deno deploy database provision my-database --kind prisma --region us-east-1453+454+# Assign to your app455+deno deploy database assign my-database --app my-app456+```457+458+For detailed CLI commands, see [Databases](references/DATABASES.md).459+460+### Local Development461+462+Use `--tunnel` to connect to your hosted development database locally:463+464+```bash465+deno task --tunnel dev466+```467+468+See [Databases](references/DATABASES.md) and [Deno KV](references/DENO_KV.md) for detailed documentation.469+470+## Local Development Tunnel471+472+The tunnel feature lets you expose your local development server to the internet. This is useful for:473+474+- **Testing webhooks** - Receive webhook callbacks from external services475+- **Sharing with teammates** - Let others preview your local work476+- **Mobile testing** - Access your local server from other devices477+478+### Basic Usage479+480+Add the `--tunnel` flag when running your app:481+482+```bash483+deno run --tunnel -A main.ts484+```485+486+The first time you run this, it will:487+1. Ask you to authenticate with Deno Deploy (opens a browser)488+2. Ask you to select which app to connect the tunnel to489+3. Generate a public URL that forwards requests to your local server490+491+### Using with Tasks492+493+You can use `--tunnel` with your existing tasks in `deno.json`:494+495+```bash496+deno task --tunnel dev497+```498+499+This runs your `dev` task with the tunnel enabled.500+501+### What the Tunnel Provides502+503+Beyond just forwarding requests, the tunnel also:504+505+- **Syncs environment variables** - Variables set in your Deno Deploy app's "Local" context become available to your local process506+- **Sends logs and metrics** - OpenTelemetry data goes to the Deno Deploy dashboard (filter with `context:local`)507+- **Connects to databases** - Automatically connects to your assigned local development databases508+509+### Managing Tunnels510+511+- View active tunnels in the Deno Deploy dashboard under the "Tunnels" tab512+- Stop a tunnel by terminating the Deno process (Ctrl+C)513+514+## Command Reference515+516+| Command | Purpose |517+|---------|---------|518+| `deno deploy --prod` | Deploy to production (app must exist first) |519+| `deno deploy` | Preview deployment |520+| `deno deploy create --org <name>` | Create new app (interactive) |521+| `deno deploy create --org <name> --app <name> ...` | Create new app (non-interactive, see full flags above) |522+| `deno deploy create ... --no-wait` | Create app without waiting for build to complete |523+| `deno deploy create ... --allow-node-modules` | Create app including node_modules |524+| `deno deploy env add <var> <value>` | Add plain text environment variable |525+| `deno deploy env add <var> <value> --secret` | Add secret environment variable |526+| `deno deploy env list` | List environment variables |527+| `deno deploy env update-value <var> <value>` | Update variable value (keeps contexts/secret status) |528+| `deno deploy env update-contexts <var> <contexts...>` | Update which contexts a variable applies to |529+| `deno deploy env delete <var>` | Delete environment variable |530+| `deno deploy env load <file>` | Load variables from .env file (defaults to secret) |531+| `deno deploy env load <file> --non-secrets <keys...>` | Load .env file, marking specific keys as non-secrets |532+| `deno deploy database provision <name> --kind <type>` | Provision a new database |533+| `deno deploy database assign <name> --app <app>` | Assign database to an app |534+| `deno deploy logs` | View deployment logs |535+| `deno run --tunnel -A <file>` | Start local tunnel |536+| `deno task --tunnel <task>` | Run task with tunnel |537+538+## Edge Runtime Notes539+540+Deno Deploy runs in one or many regions (globally distributed). Keep in mind:541+542+- **Environment variables** - Must be set via `deno deploy env`, not .env files at runtime543+- **Global distribution** - Code runs at the region closest to users544+- **Cold starts** - First request after idle may be slightly slower545+546+## Additional References547+548+- [Authentication](references/AUTHENTICATION.md) - Interactive and CI/CD authentication549+- [Databases](references/DATABASES.md) - Database provisioning and connections550+- [Deno KV](references/DENO_KV.md) - Key-value storage API and examples551+- [Domains](references/DOMAINS.md) - Custom domains and SSL certificates552+- [Frameworks](references/FRAMEWORKS.md) - Framework-specific deployment guides553+- [Organizations](references/ORGANIZATIONS.md) - Managing orgs and members554+- [Runtime](references/RUNTIME.md) - Lifecycle, cold starts, and limitations555+- [Troubleshooting](references/TROUBLESHOOTING.md) - Common issues and solutions556+557+## Documentation558+559+- Official docs: https://docs.deno.com/deploy/560+- CLI reference: https://docs.deno.com/runtime/reference/cli/deploy/561+- Databases: https://docs.deno.com/deploy/reference/databases/562+- Deno KV: https://docs.deno.com/deploy/reference/deno_kv/563+- Domains: https://docs.deno.com/deploy/reference/domains/564+- Environment variables & contexts: https://docs.deno.com/deploy/reference/env_vars_and_contexts/565+- Organizations: https://docs.deno.com/deploy/reference/organizations/566+- Runtime: https://docs.deno.com/deploy/reference/runtime/567+- Tunnel: https://docs.deno.com/deploy/reference/tunnel/
A .github/skills/deno-deploy/references/AUTHENTICATION.md +163 -0
@@ -0,0 +1,163 @@
1+# Deno Deploy Authentication2+3+## Interactive Authentication (Default)4+5+The first time you run `deno deploy`, it will open a browser for authentication:6+7+```bash8+deno deploy9+# Opens: https://console.deno.com/auth?code=XXXX-XXXX10+```11+12+**Important - Browser Device Authorization Flow:**13+- The CLI opens your browser and waits for you to complete authentication14+- You must complete the authorization in your browser before the CLI can continue15+- The CLI will not proceed automatically - it waits until you finish16+- Credentials are stored in your system keyring after successful auth17+18+**Note:** When running `deno deploy` commands that require authentication, the user must complete the browser authorization before the deployment can proceed.19+20+## Non-Interactive Authentication (CI/CD & Automation)21+22+To deploy without browser interaction (for CI/CD pipelines or automated workflows):23+24+### 1. Create a Deploy Token25+26+1. Visit https://console.deno.com/account/access-tokens27+2. Click "New Access Token"28+3. Give it a descriptive name (e.g., "GitHub Actions CI")29+4. Copy the token immediately (shown only once)30+31+### 2. Use the Token32+33+```bash34+# Option 1: Environment variable (recommended for CI/CD)35+export DENO_DEPLOY_TOKEN="your-token-here"36+deno deploy --prod37+38+# Option 2: Inline flag (for one-off commands)39+deno deploy --token "your-token-here" --prod40+```41+42+### 3. GitHub Actions Example43+44+```yaml45+- name: Deploy to Deno Deploy46+ env:47+ DENO_DEPLOY_TOKEN: ${{ secrets.DENO_DEPLOY_TOKEN }}48+ run: deno deploy --prod49+```50+51+If the app doesn't exist yet, create it first in CI/CD using non-interactive flags:52+53+```yaml54+- name: Create and deploy app55+ env:56+ DENO_DEPLOY_TOKEN: ${{ secrets.DENO_DEPLOY_TOKEN }}57+ run: |58+ deno deploy create \59+ --org my-org --app my-app \60+ --source local \61+ --runtime-mode dynamic --entrypoint main.ts \62+ --build-timeout 10 --build-memory-limit 2048 --region us63+```64+65+After the app is created, subsequent deploys only need `deno deploy --prod`.66+67+**Tip:** For fully automated deploys without browser prompts, ensure a Deno Deploy access token is set up. Create one at https://console.deno.com/account/access-tokens, then set it as the `DENO_DEPLOY_TOKEN` environment variable.68+69+## Finding Your Organization Name70+71+The Deno Deploy CLI requires an organization context for most operations. To find your org name:72+73+1. Visit https://console.deno.com74+2. Your org is in the URL: `console.deno.com/YOUR-ORG-NAME`75+76+**Note:** Commands like `deno deploy orgs` and `deno deploy switch` require an existing org context to work - this is a CLI limitation. Always find your org name from the console URL first.77+78+## Setting Up Your First App79+80+**Before creating:** Check if an app already exists:81+82+```bash83+cat deno.json | grep -A5 '"deploy"'84+```85+86+If no deploy config exists, you need to create the app first. Apps must be created before they can be deployed to.87+88+**Interactive creation** (opens a browser):89+```bash90+deno deploy create --org your-org-name91+```92+93+This opens a browser to create the app. **Important:**94+- Complete the app creation in your browser95+- The CLI waits until you finish - it won't proceed automatically96+- The app name becomes your URL: `<app-name>.deno.dev`97+98+**Non-interactive creation** (for AI agents and CI/CD — no browser needed):99+```bash100+deno deploy create \101+ --org your-org-name \102+ --app your-app-name \103+ --source local \104+ --runtime-mode dynamic \105+ --entrypoint main.ts \106+ --build-timeout 5 \107+ --build-memory-limit 1024 \108+ --region us109+```110+111+This creates the app and does the initial deploy in one step. No browser interaction required. See the main skill doc for the full list of `create` flags.112+113+**Verifying Success:** After completion, verify by checking deno.json:114+115+```bash116+cat deno.json | grep -A5 '"deploy"'117+```118+119+You should see:120+```json121+"deploy": {122+ "org": "your-org-name",123+ "app": "your-app-name"124+}125+```126+127+After this, subsequent deploys only need:128+```bash129+deno deploy --prod130+```131+132+## Interactive Commands133+134+Some `deno deploy` commands are interactive and cannot be run through automated tools.135+136+### Switching Organizations/Apps137+138+```bash139+deno deploy switch140+```141+142+This opens an interactive menu to select org and app.143+144+**Alternative - Use Explicit Flags:**145+146+Instead of interactive selection, specify org/app directly:147+148+```bash149+deno deploy --org your-org-name --app your-app-name --prod150+```151+152+This bypasses the interactive flow.153+154+## Commands That Fail Without Org Context155+156+These commands will error if no org is configured:157+- `deno deploy` (without --org flag)158+- `deno deploy orgs`159+- `deno deploy switch`160+- `deno deploy env list`161+- `deno deploy logs`162+163+Always ensure org context is set via deno.json or --org flag before running these commands.
A .github/skills/deno-deploy/references/DATABASES.md +152 -0
@@ -0,0 +1,152 @@
1+# Databases on Deno Deploy2+3+## Overview4+5+Deno Deploy provides built-in database support with automatic environment isolation. You don't need to manage connection strings or worry about mixing production and development data.6+7+## Available Database Engines8+9+| Engine | Description |10+|--------|-------------|11+| **Deno KV** | Fast, globally distributed key-value store hosted by Deno |12+| **PostgreSQL** | Connect your own PostgreSQL or provision managed Postgres via Prisma |13+14+## Key Concept: Timelines15+16+Deno Deploy automatically creates **isolated databases for each environment**:17+18+- **Production:** `{app-id}-production`19+- **Git branches:** `{app-id}--{branch-name}`20+- **Preview deployments:** `{app-id}-preview`21+22+This means your preview deployments won't accidentally modify production data.23+24+## Database CLI Commands25+26+Use `deno deploy database` to manage databases from the command line.27+28+### List Databases29+30+```bash31+# List all databases in your organization32+deno deploy database list33+34+# Search for databases by name35+deno deploy database list my-prefix36+```37+38+### Provision a Database39+40+Create a new managed database:41+42+```bash43+# Provision a new Deno KV database44+deno deploy database provision my-database --kind denokv45+46+# Provision a new Prisma PostgreSQL database (requires --region)47+deno deploy database provision my-database --kind prisma --region us-east-148+```49+50+### Link an External Database51+52+Link an existing external postgres database by providing a connection string:53+54+```bash55+deno deploy database link my-database "postgres://user:pass@host:5432/db"56+```57+58+### Assign / Detach59+60+Connect or disconnect a database from an app:61+62+```bash63+# Assign a database to an app64+deno deploy database assign my-database --app my-app65+66+# Detach a database from an app67+deno deploy database detach my-database --app my-app68+```69+70+Deno Deploy creates separate databases for each timeline automatically.71+72+### Query a Database73+74+Run queries directly from the CLI:75+76+```bash77+deno deploy database query my-database production "SELECT * FROM users LIMIT 10"78+```79+80+The second argument is the timeline name (e.g., `production`, `preview`, or a branch name), 81+which can be found in the output of `deno deploy database list`.82+83+### Delete a Database84+85+```bash86+deno deploy database delete my-database87+```88+89+## Connecting in Code90+91+### Deno KV92+93+No configuration needed - just call `Deno.openKv()`:94+95+```typescript96+const kv = await Deno.openKv();97+98+// Deno Deploy automatically connects to the right database99+// based on your current environment (production, preview, etc.)100+```101+102+### PostgreSQL103+104+Deno Deploy injects standard environment variables that most PostgreSQL libraries detect automatically:105+106+- `DATABASE_URL` - Full connection string107+- `PGHOST`, `PGPORT`, `PGDATABASE`, `PGUSER`, `PGPASSWORD` - Individual components108+109+```typescript110+// Recommended: npm:pg (best PostgreSQL driver for Deno Deploy)111+import pg from "npm:pg";112+const pool = new pg.Pool(); // Reads DATABASE_URL from environment automatically113+const { rows } = await pool.query("SELECT * FROM users");114+```115+116+## Local Development117+118+### With Tunnel119+120+Use `--tunnel` to connect your local dev server to your hosted development database:121+122+```bash123+deno task --tunnel dev124+```125+126+This gives you access to the same database environment variables locally.127+128+### Without Tunnel129+130+- **Deno KV:** Data stays in memory during local development131+- **PostgreSQL:** Point to a local PostgreSQL instance or use the tunnel132+133+## Migrations134+135+Deno Deploy supports pre-deploy commands that run before each deployment. Use these for database migrations:136+137+```json138+{139+ "deploy": {140+ "preDeploy": ["deno task db:migrate"]141+ }142+}143+```144+145+## Sharing Databases146+147+Multiple apps can share the same database instance. Each app gets its own isolated databases per timeline, even when sharing.148+149+## Documentation150+151+- Databases overview: https://docs.deno.com/deploy/reference/databases/152+- Deno KV reference: https://docs.deno.com/deploy/reference/deno_kv/
A .github/skills/deno-deploy/references/DENO_KV.md +147 -0
@@ -0,0 +1,147 @@
1+# Deno KV2+3+## What is Deno KV?4+5+Deno KV is a key-value database built into Deno. On Deno Deploy, it's a fast, globally distributed store that requires no setup or configuration.6+7+## Quick Start8+9+```typescript10+// Open the KV store (auto-connects on Deno Deploy)11+const kv = await Deno.openKv();12+13+// Store a value14+await kv.set(["users", "alice"], { name: "Alice", email: "alice@example.com" });15+16+// Retrieve a value17+const result = await kv.get(["users", "alice"]);18+console.log(result.value); // { name: "Alice", email: "alice@example.com" }19+20+// Delete a value21+await kv.delete(["users", "alice"]);22+```23+24+## Keys25+26+Keys are arrays of "key parts" that form a hierarchy:27+28+```typescript29+// Simple key30+["settings"]31+32+// Hierarchical keys33+["users", "alice"]34+["users", "bob"]35+["posts", "2024", "01", "my-post"]36+```37+38+Key parts can be strings, numbers, booleans, Uint8Array, or bigints.39+40+## Basic Operations41+42+### Get43+44+```typescript45+const result = await kv.get<User>(["users", "alice"]);46+if (result.value) {47+ console.log(result.value.name);48+}49+```50+51+### Set52+53+```typescript54+await kv.set(["users", "alice"], { name: "Alice" });55+56+// With expiration (in milliseconds)57+await kv.set(["sessions", sessionId], data, { expireIn: 3600000 }); // 1 hour58+```59+60+### Delete61+62+```typescript63+await kv.delete(["users", "alice"]);64+```65+66+### List67+68+```typescript69+// List all users70+const users = kv.list<User>({ prefix: ["users"] });71+for await (const entry of users) {72+ console.log(entry.key, entry.value);73+}74+75+// With limit76+const firstTen = kv.list<User>({ prefix: ["users"] }, { limit: 10 });77+```78+79+## Atomic Transactions80+81+Perform multiple operations atomically (all succeed or all fail):82+83+```typescript84+// Transfer credits between users85+const alice = await kv.get<number>(["credits", "alice"]);86+const bob = await kv.get<number>(["credits", "bob"]);87+88+const result = await kv.atomic()89+ .check(alice) // Ensure alice hasn't changed90+ .check(bob) // Ensure bob hasn't changed91+ .set(["credits", "alice"], alice.value! - 100)92+ .set(["credits", "bob"], bob.value! + 100)93+ .commit();94+95+if (!result.ok) {96+ console.log("Transaction failed - data was modified");97+}98+```99+100+## Example: Request Counter101+102+```typescript103+const kv = await Deno.openKv();104+105+Deno.serve(async () => {106+ // Increment counter atomically107+ const key = ["requests"];108+109+ let result = { ok: false };110+ while (!result.ok) {111+ const current = await kv.get<number>(key);112+ const newCount = (current.value ?? 0) + 1;113+114+ result = await kv.atomic()115+ .check(current)116+ .set(key, newCount)117+ .commit();118+ }119+120+ const count = (await kv.get<number>(key)).value;121+ return new Response(`Requests: ${count}`);122+});123+```124+125+## Data Location126+127+On Deno Deploy, KV data is replicated across at least three data centers in Northern Virginia (us-east-4). Cross-region replication is not currently available.128+129+## Local Development130+131+When running locally with `deno run`, KV data is stored in memory by default. For persistent local storage:132+133+```typescript134+// Persist to a local file135+const kv = await Deno.openKv("./my-database.sqlite");136+```137+138+## Important Notes139+140+- **Deletion is permanent** - Deleting a KV instance removes all data with no recovery141+- **Back up important data** before deleting instances142+- **No cross-region replication** yet - data lives in us-east-4143+144+## Documentation145+146+- Deno KV on Deploy: https://docs.deno.com/deploy/reference/deno_kv/147+- Deno KV API: https://docs.deno.com/api/deno/~/Deno.Kv
A .github/skills/deno-deploy/references/DOMAINS.md +88 -0
@@ -0,0 +1,88 @@
1+# Custom Domains2+3+## Default Domain4+5+Every organization gets a default domain: `your-org.deno.net`6+7+Apps are accessible at: `your-app.deno.dev`8+9+## Adding a Custom Domain10+11+1. Go to your organization's domains page in the Deno Deploy dashboard12+2. Click "Add Domain"13+3. Enter your domain (e.g., `example.com` or `*.example.com` for wildcards)14+4. Click "Add Domain" to see DNS configuration15+16+## DNS Configuration17+18+You have three options for DNS setup:19+20+### Option 1: ANAME/ALIAS (Recommended)21+22+Best option if your registrar supports ANAME or ALIAS records.23+24+| Record Type | Name | Value |25+|-------------|------|-------|26+| ANAME/ALIAS | `@` | `<your-app>.deno.dev` |27+| CNAME | `_acme-challenge` | (provided in dashboard) |28+29+### Option 2: CNAME30+31+Works for subdomains (like `api.example.com`) but **not for apex domains** (like `example.com`).32+33+| Record Type | Name | Value |34+|-------------|------|-------|35+| CNAME | `api` | `<your-app>.deno.dev` |36+| CNAME | `_acme-challenge.api` | (provided in dashboard) |37+38+### Option 3: A Record39+40+Most compatible, works with any registrar.41+42+| Record Type | Name | Value |43+|-------------|------|-------|44+| A | `@` | (IP provided in dashboard) |45+| CNAME | `_acme-challenge` | (provided in dashboard) |46+47+**Note:** IPv6 is not supported with the A record method.48+49+## Cloudflare Users50+51+If using Cloudflare, **disable proxying** (turn off the orange cloud) on the `_acme-challenge` CNAME record. Proxying prevents certificate verification from completing.52+53+## SSL/TLS Certificates54+55+### Automatic Certificates (Recommended)56+57+After DNS verification completes:58+1. Click "Provision Certificate" in the dashboard59+2. Let's Encrypt generates your certificate60+3. Certificates renew automatically61+62+### Bring Your Own Certificate63+64+If you need a specific certificate:65+1. Upload your PEM-formatted certificate file66+2. Upload your private key file67+3. **You must manage renewal** - notifications arrive 14 days before expiration68+69+**Warning:** Expired certificates cause your domain to stop working.70+71+## Assigning Domains to Apps72+73+1. Go to organization domains page74+2. Find your domain and click to edit75+3. Assign it to an application76+4. Remove assignments from app settings if needed77+78+## Troubleshooting79+80+| Issue | Solution |81+|-------|----------|82+| Verification stuck | Check DNS propagation (can take up to 48 hours) |83+| Certificate won't provision | Ensure `_acme-challenge` CNAME is correct and not proxied |84+| IPv6 not working | Use ANAME/ALIAS or CNAME instead of A record |85+86+## Documentation87+88+- Domains reference: https://docs.deno.com/deploy/reference/domains/
A .github/skills/deno-deploy/references/FRAMEWORKS.md +197 -0
@@ -0,0 +1,197 @@
1+# Framework-Specific Deployment2+3+Deno Deploy supports multiple frameworks. The CLI auto-detects your framework and configures the build appropriately.4+5+## Framework Detection6+7+| Framework | Detection Files | Build Command | Notes |8+|-----------|-----------------|---------------|-------|9+| **Fresh** | `islands/`, `fresh.config.ts` | `deno task build` | Deno-native, island architecture |10+| **Astro** | `astro.config.mjs`, `astro.config.ts` | `npm run build` or `deno task build` | Static or SSR |11+| **Next.js** | `next.config.js`, `next.config.mjs` | `npm run build` | Requires `nodeModulesDir: "auto"` |12+| **Nuxt** | `nuxt.config.ts` | `npm run build` | Vue SSR framework |13+| **Remix** | `remix.config.js` | `npm run build` | React SSR framework |14+| **SolidStart** | `app.config.ts` with solid | `npm run build` | SolidJS SSR |15+| **SvelteKit** | `svelte.config.js` | `npm run build` | Svelte SSR framework |16+| **Lume** | `_config.ts` with lume import | `deno task build` | Deno-native static site |17+18+## Framework Presets for `deno deploy create`19+20+When creating an app with `deno deploy create` in non-interactive mode, you can specify `--framework-preset` to auto-configure build commands and runtime settings. The available presets are: `Fresh`, `Next`, `Remix`, `Astro`, `SvelteKit`, `Nuxt`, `Lume`, `SolidStart`.21+22+When a preset is specified, you can omit `--install-command`, `--build-command`, `--pre-deploy-command`, and `--runtime-mode` — they are inferred from the preset.23+24+If you don't specify a preset, the CLI still auto-detects your framework from the project files. Use `--do-not-use-detected-build-config` to skip auto-detection and specify everything manually.25+26+## Detect Framework Script27+28+```bash29+if [ -d "islands" ] || [ -f "fresh.config.ts" ]; then echo "Framework: Fresh"; \30+elif [ -f "astro.config.mjs" ] || [ -f "astro.config.ts" ]; then echo "Framework: Astro"; \31+elif [ -f "next.config.js" ] || [ -f "next.config.mjs" ]; then echo "Framework: Next.js"; \32+elif [ -f "nuxt.config.ts" ]; then echo "Framework: Nuxt"; \33+elif [ -f "remix.config.js" ]; then echo "Framework: Remix"; \34+elif [ -f "svelte.config.js" ]; then echo "Framework: SvelteKit"; \35+elif [ -f "_config.ts" ]; then echo "Framework: Lume (check imports)"; \36+else echo "Framework: Custom/Unknown"; fi37+```38+39+## Fresh (Deno-Native)40+41+```bash42+deno task build43+deno deploy --prod44+```45+46+## Fresh + PostgreSQL47+48+When a Fresh app uses PostgreSQL (e.g., `await initDb()` at startup), you must provision the database **before** the app can successfully warm up. The Fresh auto-detection preset also has a known issue, so use manual build config.49+50+**Complete deployment sequence:**51+52+```bash53+# 1. Create the app with --no-wait (warmup will fail without a database — that's expected)54+deno deploy create \55+ --org <ORG_NAME> --app <APP_NAME> \56+ --source local \57+ --do-not-use-detected-build-config \58+ --install-command "deno install" \59+ --build-command "deno task build" \60+ --pre-deploy-command "echo ready" \61+ --runtime-mode dynamic --entrypoint main.ts \62+ --build-timeout 5 --build-memory-limit 1024 --region us \63+ --no-wait64+65+# 2. Provision a PostgreSQL database66+deno deploy database provision my-db --kind prisma --region us-east-167+68+# 3. Assign it to the app (this injects DATABASE_URL, PGHOST, etc.)69+deno deploy database assign my-db --app <APP_NAME>70+71+# 4. Redeploy — now the database exists, so warmup succeeds72+deno deploy --prod73+```74+75+**Why this order matters:**76+- Fresh + PostgreSQL apps typically call `await initDb()` in `main.ts`, which runs during warmup77+- If no database is assigned, the connection fails and the deploy is marked as failed78+- Using `--no-wait` on the first deploy lets you continue to the database setup without blocking79+80+**Why `--do-not-use-detected-build-config`:**81+- The Fresh auto-detection and `--framework-preset fresh` can fail with an API error82+- Manual build config is more reliable — see [Troubleshooting](TROUBLESHOOTING.md#fresh-auto-detection--preset-fails)83+84+## Astro85+86+```bash87+# If using npm88+npm run build89+deno deploy --prod90+91+# If using Deno tasks92+deno task build93+deno deploy --prod94+```95+96+## Next.js97+98+Next.js requires Node.js compatibility mode:99+100+1. Ensure `deno.json` has:101+ ```json102+ {103+ "nodeModulesDir": "auto"104+ }105+ ```106+107+2. Build and deploy:108+ ```bash109+ npm install110+ npm run build111+ deno deploy --prod --allow-node-modules112+ ```113+114+## Nuxt / Remix / SvelteKit / SolidStart115+116+These npm-based frameworks follow a similar pattern:117+118+```bash119+npm install120+npm run build121+deno deploy --prod122+```123+124+If you encounter issues with node_modules:125+```bash126+deno deploy --prod --allow-node-modules127+```128+129+## Lume (Static Sites)130+131+```bash132+deno task build133+deno deploy --prod134+```135+136+## Custom / No Framework137+138+For custom servers or apps without a recognized framework:139+140+1. Ensure you have an entrypoint (e.g., `main.ts`, `server.ts`)141+2. Deploy directly:142+ ```bash143+ deno deploy --entrypoint main.ts --prod144+ ```145+146+## Static Site Deployment147+148+For static sites (Lume, Vite builds, etc.), you have two options:149+150+### Option 1: Direct Directory Deployment151+152+Point Deno Deploy at your built directory. Configure in `deno.json`:153+154+```json155+{156+ "deploy": {157+ "entrypoint": "main.ts",158+ "include": ["_site"]159+ }160+}161+```162+163+### Option 2: Custom Server Wrapper164+165+Only needed if you want custom routing, headers, or logic:166+167+```typescript168+// serve.ts169+import { serveDir } from "jsr:@std/http/file-server";170+171+Deno.serve((req) =>172+ serveDir(req, {173+ fsRoot: "_site",174+ quiet: true,175+ })176+);177+```178+179+Then deploy with:180+181+```bash182+deno deploy --entrypoint serve.ts --prod183+```184+185+## Cloud Integrations186+187+### AWS Integration188+189+```bash190+deno deploy setup-aws --org my-org --app my-app191+```192+193+### GCP Integration194+195+```bash196+deno deploy setup-gcp --org my-org --app my-app197+```
A .github/skills/deno-deploy/references/ORGANIZATIONS.md +79 -0
@@ -0,0 +1,79 @@
1+# Organizations2+3+## What is an Organization?4+5+In Deno Deploy, an organization is a group where users collectively own apps and domains. Every user belongs to an organization - all resources (apps, domains, environment variables) exist at the organization level.6+7+Each organization has:8+- **Name:** Displayed in the dashboard9+- **Slug:** Part of your default domain (e.g., `acme-inc.deno.net`)10+11+**Important:** The slug cannot be changed after creation.12+13+## Creating an Organization14+15+Organizations are created automatically during Deno Deploy signup:16+17+1. Visit https://console.deno.com18+2. Sign in with GitHub19+3. Create your organization as part of setup20+21+## Finding Your Organization22+23+Your org name appears in the console URL:24+```25+https://console.deno.com/YOUR-ORG-NAME26+```27+28+Use this for CLI commands:29+```bash30+deno deploy create --org YOUR-ORG-NAME31+deno deploy --org YOUR-ORG-NAME --prod32+```33+34+## Managing Members35+36+### Inviting Users37+38+1. Go to organization settings in the dashboard39+2. Click "+ Invite User"40+3. Enter the person's GitHub username (e.g., `ry`)41+4. Optionally add their email address42+5. Send the invitation43+44+The invitee receives an email with a link to accept.45+46+### Removing Members47+48+1. Go to organization settings49+2. Find the user in the members table50+3. Click remove and confirm51+52+### Canceling Invitations53+54+Pending invitations can be cancelled before the person accepts.55+56+## Permissions57+58+Currently, **all members have owner permissions**. Every member can:59+- Invite and remove other members60+- Create and delete apps61+- Manage domains62+- Configure environment variables63+- Deploy to production64+65+There is no tiered permission system yet.66+67+## Organization Deletion68+69+Organizations **cannot be deleted through the dashboard**. Contact Deno support if you need to delete an organization.70+71+## Best Practices72+73+- **Choose your slug carefully** - it's permanent and visible in URLs74+- **Limit membership** - since all members have full access75+- **Use descriptive app names** - they become part of URLs too76+77+## Documentation78+79+- Organizations reference: https://docs.deno.com/deploy/reference/organizations/
A .github/skills/deno-deploy/references/RUNTIME.md +90 -0
@@ -0,0 +1,90 @@
1+# Deno Deploy Runtime2+3+## Overview4+5+Deno Deploy uses the standard Deno runtime. You can use JSR and NPM packages, filesystem operations, network requests, subprocesses, and FFI/native addons.6+7+## Current Environment8+9+- **Runtime:** Deno 2.5.010+- **Platform:** Linux (x64 or ARM64)11+- **Permissions:** All permissions enabled automatically (`--allow-all`)12+13+**Note:** Custom Deno flags cannot be passed to the runtime.14+15+## Serverless Lifecycle16+17+Understanding how your app starts and stops is important for building reliable applications.18+19+### Startup20+21+Your application starts when a request arrives. If your app crashes before the HTTP server starts, requests return a 502 error.22+23+**Tip:** Keep startup fast by:24+- Reducing dependencies25+- Using dynamic imports for rarely-used code26+- Avoiding network requests during startup27+28+### Idle Shutdown29+30+After 5-10 minutes without requests:31+1. The system sends a `SIGINT` signal32+2. Your app has 5 seconds to shut down gracefully33+3. If still running, `SIGKILL` terminates it34+35+```typescript36+// Handle graceful shutdown37+Deno.addSignalListener("SIGINT", () => {38+ console.log("Shutting down...");39+ // Clean up resources, close connections40+ Deno.exit(0);41+});42+```43+44+### Eviction45+46+Even during active traffic, instances may be terminated due to:47+- Infrastructure updates48+- Resource constraints49+50+The system redirects traffic first, then signals shutdown. **Long-running connections should expect reconnections.**51+52+## Cold Start Performance53+54+Cold starts typically complete:55+- **~100ms** for simple "hello world" apps56+- **A few hundred ms** for larger applications57+58+Deno Deploy optimizes cold starts using:59+- Pre-provisioned microVMs60+- Early TCP connection setup61+- File system warmup62+63+### Minimizing Cold Start Time64+65+```typescript66+// BAD: Top-level network request delays startup67+const config = await fetch("https://api.example.com/config").then(r => r.json());68+69+// GOOD: Lazy load on first request70+let config: Config | null = null;71+async function getConfig() {72+ if (!config) {73+ config = await fetch("https://api.example.com/config").then(r => r.json());74+ }75+ return config;76+}77+```78+79+## Limitations80+81+| Feature | Status |82+|---------|--------|83+| Custom Deno flags | Not supported |84+| Persistent filesystem | Use Deno KV instead |85+| Long-running background tasks | May be interrupted |86+| System tools | Available but may change |87+88+## Documentation89+90+- Runtime reference: https://docs.deno.com/deploy/reference/runtime/
A .github/skills/deno-deploy/references/TROUBLESHOOTING.md +174 -0
@@ -0,0 +1,174 @@
1+# Deno Deploy Troubleshooting2+3+## First Step: Use `--help`4+5+Before debugging a failed command, run `--help` to confirm the flags you're using actually exist and are spelled correctly:6+7+```bash8+deno deploy create --help9+deno deploy env --help10+deno deploy database --help11+```12+13+Exit code 2 almost always means a flag is missing or invalid — `--help` will show you exactly what's required.14+15+## Common Errors16+17+### "No organization was selected"18+19+This error occurs because the CLI needs an organization context. Unfortunately, commands like `deno deploy orgs` also fail without this context.20+21+**Solution:**22+23+1. **Find your org name manually:** Visit https://console.deno.com - your org is in the URL path (e.g., `console.deno.com/donjo` means org is `donjo`)24+25+2. **Specify org explicitly:**26+ ```bash27+ deno deploy --org your-org-name --prod28+ ```29+30+3. **Or create an app with org:**31+ ```bash32+ deno deploy create --org your-org-name33+ # Complete the browser flow when prompted34+ ```35+36+If you see this error, the user needs to provide their organization name from the console URL.37+38+### "No entrypoint found"39+40+Specify your entry file:41+42+```bash43+deno deploy --entrypoint main.ts --prod44+```45+46+Or add to `deno.json`:47+48+```json49+{50+ "deploy": {51+ "entrypoint": "main.ts"52+ }53+}54+```55+56+### "authorization required"57+58+Token expired or missing. Options:59+- Re-authenticate interactively (browser flow)60+- Set up a CI/CD token via `DENO_DEPLOY_TOKEN` environment variable61+- Create a new token at https://console.deno.com/account/access-tokens62+63+### "Minimum Deno version required"64+65+User needs to upgrade Deno:66+```bash67+deno upgrade68+```69+70+The `deno deploy` command requires Deno >= 2.4.2.71+72+### Fresh "Build required" Error73+74+Fresh 2.0 requires building before deployment:75+76+```bash77+deno task build78+deno deploy --prod79+```80+81+### Environment Variable Errors82+83+Check what's currently set:84+85+```bash86+deno deploy env list87+```88+89+Add missing variables:90+91+```bash92+deno deploy env add MISSING_VAR "value"93+```94+95+### Warmup Failure After Deploy96+97+The build succeeds but the deploy fails with a warmup error or exit code 1. This usually means the app crashes on startup.98+99+**Most common cause:** The app connects to a database at startup (e.g., `await initDb()` in `main.ts`), but no database has been provisioned or assigned yet.100+101+**Solution:**102+103+1. Provision and assign the database:104+ ```bash105+ deno deploy database provision my-db --kind prisma --region us-east-1106+ deno deploy database assign my-db --app <APP_NAME>107+ ```108+109+2. Redeploy:110+ ```bash111+ deno deploy --prod112+ ```113+114+For a complete walkthrough, see the [Fresh + PostgreSQL recipe](FRAMEWORKS.md#fresh--postgresql).115+116+### Fresh Auto-Detection / Preset Fails117+118+When the CLI auto-detects Fresh or you use `--framework-preset fresh`, the deploy may fail with an API error. This is a known issue.119+120+**Workaround:** Use `--do-not-use-detected-build-config` and specify all build commands manually:121+122+```bash123+deno deploy create \124+ --org <ORG_NAME> --app <APP_NAME> \125+ --source local \126+ --do-not-use-detected-build-config \127+ --install-command "deno install" \128+ --build-command "deno task build" \129+ --pre-deploy-command "echo ready" \130+ --runtime-mode dynamic --entrypoint main.ts \131+ --build-timeout 5 --build-memory-limit 1024 --region us132+```133+134+## Error Response Table135+136+| Error | Cause | Solution |137+|-------|-------|----------|138+| "No organization was selected" | No org in config | Get org name from console URL, use `--org` flag |139+| "No entrypoint found" | Can't find main file | Use `--entrypoint` flag or set in deno.json |140+| "authorization required" | Token expired/missing | Re-authenticate or set `DENO_DEPLOY_TOKEN` |141+| "Minimum Deno version required" | Deno too old | Run `deno upgrade` |142+| Exit code 2 (usage error) | Missing or invalid flags | Run `deno deploy create --help` to see required flags |143+| Warmup failure (exit code 1) | App crashes on startup | Check for missing database or env vars — see [Warmup Failure](#warmup-failure-after-deploy) |144+| Fresh preset API error | Auto-detection bug | Use `--do-not-use-detected-build-config` — see [Fresh workaround](#fresh-auto-detection--preset-fails) |145+146+## Verifying Deployment Success147+148+The CLI output can be verbose. Look for these indicators of success:149+- A URL containing `.deno.dev` or `.deno.net` - this is your live deployment150+- A console URL like `https://console.deno.com/<org>/<app>/builds/<id>`151+- The command exits with code 0 (no error)152+153+After deployment, confirm success by extracting the production URL from the output. The format is typically:154+`https://<app-name>.<org>.deno.net` or `https://<app-name>.deno.dev`155+156+## Commands That Require Org Context157+158+These commands will error if no org is configured - do not try them to "discover" orgs:159+- `deno deploy` (without --org flag)160+- `deno deploy orgs`161+- `deno deploy switch`162+- `deno deploy env list`163+- `deno deploy logs`164+165+## Environment Variable Contexts166+167+Variables can apply to different environments:168+169+```bash170+# Set which contexts a variable applies to171+deno deploy env update-contexts API_KEY Production Preview172+```173+174+Available contexts: `Production`, `Preview`, `Local`, `Build`
A .github/skills/deno-expert/SKILL.md +255 -0
@@ -0,0 +1,255 @@
1+---2+name: deno-expert3+description: Expert-level Deno knowledge for code review, debugging, and best practice enforcement. Use when reviewing Deno code or answering advanced Deno questions.4+license: MIT5+metadata:6+ author: denoland7+ version: "1.1"8+---9+10+# Deno Expert Knowledge11+12+This skill provides expert-level Deno knowledge for code review, debugging, and best practice enforcement.13+14+## When to Use This Skill15+16+- Reviewing Deno/Fresh code for best practices17+- Debugging Deno runtime issues18+- Answering advanced Deno questions19+- Evaluating package choices20+- Setting up Deno projects correctly21+22+## Scope Boundaries23+24+This skill applies **only** to Deno-specific questions. Follow these rules:25+26+- If the user asks about **Node.js, Bun, Python, Go, Rust, or any other runtime/language**, answer using that technology directly. Do not suggest Deno alternatives or include Deno-specific patterns.27+- Do not include `jsr:` imports, `deno add`, `deno fmt`, `deno lint`, `deno test`, or `deno.json` configuration in responses about other technologies.28+- For **generic TypeScript/JavaScript questions** not tied to a specific runtime, give a general answer without assuming Deno.29+- Only recommend Deno when the user explicitly asks about Deno or is working in a Deno project.30+31+## CRITICAL: Never Write Deprecated URLs32+33+When discussing deprecated patterns, NEVER write out the old registry URLs — not even to warn against them. The string `deno.land/x/` must never appear in your response, in any context.34+35+- Say "the old URL-based registry" or "deprecated URL imports" — do NOT write the actual URL36+- Say "the old standard library URL" — do NOT write `deno.land/std`37+- When helping users migrate, describe what to look for generically and ONLY show the correct modern code38+- Do NOT write "before/after" comparisons that include the deprecated URL, even as negative examples39+- Even if the user writes a deprecated URL in their question, do NOT echo it back. Refer to it generically.40+- This ban applies everywhere: prose, code blocks, migration scripts, sed commands, grep patterns, and string literals. Never write the deprecated URL string for any reason.41+42+## Core Expertise Areas43+44+Understanding these topics deeply:45+- **Deno runtime** - Permissions, built-in tools, TypeScript support46+- **Fresh framework** - Island architecture, routing, components47+- **JSR packages** - The modern registry, @std/* library48+- **Preact** - Components, hooks, signals49+- **Deno Deploy** - Edge deployment, environment variables50+- **Deno Sandboxes** - Safe code execution with @deno/sandbox51+52+## Package Recommendation Principles53+54+When recommending or reviewing package choices:55+56+1. **First choice:** `jsr:` packages (e.g., `jsr:@std/http`)57+2. **Second choice:** `npm:` packages when no JSR alternative exists58+3. **Never recommend** the old URL-based registry — it is deprecated59+60+The standard library is at `jsr:@std/*` on JSR.61+62+Always mention JSR when discussing dependencies, even in CI/CD or tooling contexts. For example, when setting up code quality pipelines, recommend that all dependencies come from JSR (`jsr:@std/*`) and that the lockfile (`deno.lock`) be committed for reproducible CI builds.63+64+## Built-in Tool Usage65+66+**In every response that involves Deno code** (not just code reviews), mention relevant built-in tools. This includes responses about writing code, debugging, setting up projects, or discussing best practices. Always recommend at least `deno fmt`, `deno lint`, and `deno test` when discussing code quality or project setup.67+68+Deno's integrated tooling:69+- `deno fmt` - Format code70+- `deno lint` - Lint for issues71+- `deno test` - Run tests72+- `deno check` - Type-check code73+- `deno doc <package>` - View package documentation74+- `deno add <package>` - Add dependencies75+- `deno deploy` - Deploy to Deno Deploy76+77+## Code Review Checklist78+79+### Always Mention Built-in Tools80+81+In every code review response, explicitly recommend these tools by name:82+- `deno fmt` for formatting83+- `deno lint` for linting84+- `deno test` for running tests85+86+Even if no code is provided yet, mention these specific commands when discussing code quality.87+88+### Import Statements89+- [ ] Uses `jsr:` for Deno-native packages90+- [ ] Uses `npm:` only when no JSR alternative exists91+- [ ] No imports from the old URL-based registry (deprecated)92+- [ ] No old URL-based standard library imports (use `jsr:@std/*`)93+- [ ] Standard library uses `jsr:@std/*`94+95+### Configuration96+- [ ] Has a proper `deno.json` configuration97+- [ ] Import maps defined in `deno.json` (not separate file)98+- [ ] Correct permissions in run commands99+100+### Fresh Applications101+- [ ] Islands are small and focused (minimal JavaScript to client)102+- [ ] Props passed to islands are JSON-serializable (no functions)103+- [ ] Non-interactive components are in `components/`, not `islands/`104+- [ ] Uses `class` instead of `className` (Preact supports both)105+- [ ] Build step runs before deployment (`deno task build`)106+107+### Code Quality108+- [ ] Code is formatted (`deno fmt`)109+- [ ] Code passes linting (`deno lint`)110+- [ ] Tests exist and pass (`deno test`)111+- [ ] Documentation exists for public APIs112+113+## Common Anti-Patterns to Flag114+115+When reviewing code, describe deprecated patterns generically and only show the correct modern replacement. Never write out the deprecated code.116+117+### URL-based imports (deprecated)118+119+When you see old URL-based imports from the deprecated registry, flag them and guide the user to:120+1. Find the package on jsr.io121+2. Run `deno add jsr:@package/name`122+3. Use the bare specifier123+124+Only show the correct approach:125+```ts126+import * as oak from "@oak/oak";127+import { join } from "@std/path";128+```129+130+### Old standard library imports (deprecated)131+132+When you see imports from the old standard library URL, suggest the JSR equivalent:133+134+```sh135+deno add jsr:@std/path136+```137+138+```ts139+import { join } from "@std/path";140+```141+142+### Inline remote specifiers143+144+When you see inline `jsr:` or `npm:` specifiers in import statements (and a `deno.json` exists), suggest moving them to the import map:145+146+```sh147+deno add jsr:@oak/oak148+deno add npm:chalk149+```150+151+```ts152+import * as oak from "@oak/oak";153+import chalk from "chalk";154+```155+156+Inline specifiers are fine in single file scripts, but if a deno.json exists then it should go there. It's preferable to place npm dependencies in a package.json if a package.json exists.157+158+### Wrong: Entire page as island159+```tsx160+// Flag: Too much JavaScript shipped to client161+// islands/HomePage.tsx162+export default function HomePage() {163+ return (164+ <div>165+ <Header />166+ <MainContent />167+ <Footer />168+ </div>169+ );170+}171+172+// Suggest: Only interactive parts as islands173+// routes/index.tsx174+import Counter from "../islands/Counter.tsx";175+176+export default function HomePage() {177+ return (178+ <div>179+ <Header />180+ <MainContent />181+ <Counter /> {/* Only this needs interactivity */}182+ <Footer />183+ </div>184+ );185+}186+```187+188+### Wrong: Non-serializable island props189+```tsx190+// Flag this191+<Counter onUpdate={(val) => console.log(val)} />192+193+// Suggest this194+<Counter initialValue={5} label="Click count" />195+```196+197+## Debugging Guidance198+199+### Permission Errors200+Check if permissions are correct (`--allow-net`, `--allow-read`, etc.):201+```bash202+deno run --allow-net server.ts203+```204+205+### TypeScript Errors206+Check for TypeScript errors:207+```bash208+deno check main.ts209+```210+211+### Configuration Issues212+Review deno.json for correct configuration. Ensure all `jsr:` and `npm:` specifiers have a version requirement:213+214+```json215+{216+ "imports": {217+ "@std/http": "jsr:@std/http@^1"218+ }219+}220+```221+222+## Documentation Resources223+224+When more information is needed, consult:225+- https://docs.deno.com - Deno docs226+- https://docs.deno.com/runtime/fundamentals/ - Core concepts227+- https://fresh.deno.dev/docs - Fresh framework228+- https://jsr.io - Package registry229+- https://docs.deno.com/deploy/ - Deno Deploy230+231+Use `deno doc <package>` to get API documentation for any package locally.232+233+## Quick Commands Reference234+235+```bash236+# Project setup237+deno run -Ar jsr:@fresh/init # New Fresh project238+239+# Development240+deno task dev # Start dev server (Fresh: port 5173)241+deno fmt # Format code242+deno lint # Lint code243+deno test # Run tests244+245+# Packages246+deno add jsr:@std/http # Add package247+deno doc jsr:@std/http # View docs248+deno install # Install all deps249+deno upgrade # Update packages250+251+# Deployment252+deno task build # Build for production253+deno deploy --prod # Deploy to Deno Deploy254+deno deploy env add KEY "value" # Set env variable255+```
A .github/skills/deno-frontend/SKILL.md +886 -0
@@ -0,0 +1,886 @@
1+---2+name: deno-frontend3+description: Use when working with Fresh framework, creating routes or handlers in Fresh, building web UIs with Preact, or adding Tailwind CSS in Deno. Covers Fresh 2.x project structure, route handlers, islands, createDefine, PageProps, context patterns, and Fresh 1.x to 2.x migration. Essential for any Fresh-related question.4+license: MIT5+metadata:6+ author: denoland7+ version: "2.4"8+---9+10+# Deno Frontend Development11+12+## Overview13+14+This skill covers frontend development in Deno using Fresh 2.x (Deno's web framework), Preact (a lightweight React alternative), and Tailwind CSS. Fresh uses "island architecture" where pages render on the server and only interactive parts ship JavaScript to the browser.15+16+## When to Use This Skill17+18+- Creating a new Fresh web application19+- Building interactive UI components (islands)20+- Adding server-rendered pages and routes21+- Integrating Tailwind CSS for styling22+- Choosing between islands (client-side) vs components (server-only)23+- Working with Preact hooks and signals24+25+Apply these practices when building web applications in Deno.26+27+## Scope Boundaries28+29+This skill applies **only** to Fresh/Deno frontend questions. Follow these rules:30+31+- If the user asks about **Next.js, React Native, Vue, Svelte, Angular, or any other framework**, answer using that framework directly. Do not suggest Fresh alternatives.32+- Do not include Fresh imports, `useSignal`, island patterns, or Fresh project structure in responses about other frameworks.33+- Only recommend Fresh when the user explicitly asks about Fresh or is working in a Fresh/Deno project.34+35+## CRITICAL: Never Show Deprecated Syntax36+37+When helping users migrate from Fresh 1.x, describe old patterns generically and ONLY show correct Fresh 2.x code. Never write out old dollar-sign import paths or deprecated syntax, even in "before/after" comparisons.38+39+- Say "Replace the old dollar-sign import paths with stable Fresh 2.x imports" — then show only the correct `from "fresh"` approach40+- Do NOT write `❌ Old: import { App } from "$fresh/server.ts"` — this is never acceptable, even as a negative example41+- The strings `_404.tsx` and `_500.tsx` must never appear in your response, even when comparing Fresh 2.x to 1.x. Say "the old separate error pages" instead.42+43+Only demonstrate Fresh 2.x patterns.44+45+## CRITICAL: Fresh 2.x vs 1.x46+47+**Always use Fresh 2.x patterns.** Fresh 1.x is deprecated. Key differences:48+49+- Fresh 2.x uses `import { App } from "fresh"` — the old dollar-sign import paths are deprecated50+- Fresh 2.x has no manifest file — the old auto-generated manifest is no longer needed51+- Fresh 2.x uses `vite.config.ts` for dev — the old `dev.ts` entry point is gone52+- Fresh 2.x configures via `new App()` — the old config file is no longer used53+- Fresh 2.x handlers take a single `(ctx)` parameter — the old two-parameter signature is deprecated54+- Fresh 2.x uses a unified `_error.tsx` — the old separate error pages are replaced55+56+**Always use Fresh 2.x stable imports:**57+```typescript58+// ✅ CORRECT - Fresh 2.x stable59+import { App, staticFiles } from "fresh";60+import { define } from "./utils/state.ts"; // Project-local define helpers61+```62+63+## Fresh Framework64+65+Reference: https://fresh.deno.dev/docs66+67+Fresh is Deno's web framework. It uses **island architecture** - pages are rendered on the server, and only interactive parts ("islands") get JavaScript on the client.68+69+### Creating a Fresh Project70+71+```bash72+deno run -Ar jsr:@fresh/init73+cd my-project74+deno task dev # Runs at http://127.0.0.1:5173/75+```76+77+### Project Structure (Fresh 2.x)78+79+```80+my-project/81+├── deno.json # Config, dependencies, and tasks82+├── main.ts # Server entry point83+├── client.ts # Client entry point (CSS imports)84+├── vite.config.ts # Vite configuration85+├── routes/ # Pages and API routes86+│ ├── _app.tsx # App layout wrapper (outer HTML)87+│ ├── _layout.tsx # Layout component (optional)88+│ ├── _error.tsx # Unified error page (404/500)89+│ ├── index.tsx # Home page (/)90+│ └── api/ # API routes91+├── islands/ # Interactive components (hydrated on client)92+│ └── Counter.tsx93+├── components/ # Server-only components (no JS shipped)94+│ └── Button.tsx95+├── static/ # Static assets96+└── utils/97+ └── state.ts # Define helpers for type safety98+```99+100+**Note:** Fresh 2.x does not use a manifest file, a separate dev entry point, or a separate config file.101+102+### main.ts (Fresh 2.x Entry Point)103+104+```typescript105+import { App, fsRoutes, staticFiles, trailingSlashes } from "fresh";106+107+const app = new App()108+ .use(staticFiles())109+ .use(trailingSlashes("never"));110+111+await fsRoutes(app, {112+ dir: "./",113+ loadIsland: (path) => import(`./islands/${path}`),114+ loadRoute: (path) => import(`./routes/${path}`),115+});116+117+if (import.meta.main) {118+ await app.listen();119+}120+```121+122+### vite.config.ts123+124+```typescript125+import { defineConfig } from "vite";126+import { fresh } from "@fresh/plugin-vite";127+import tailwindcss from "@tailwindcss/vite";128+129+export default defineConfig({130+ plugins: [131+ fresh(),132+ tailwindcss(),133+ ],134+});135+```136+137+### deno.json Configuration138+139+A Fresh 2.x project's deno.json looks like this (created by `jsr:@fresh/init`):140+141+```json142+{143+ "tasks": {144+ "dev": "vite",145+ "build": "vite build",146+ "preview": "deno serve -A _fresh/server.js"147+ },148+ "imports": {149+ "fresh": "jsr:@fresh/core@^2",150+ "fresh/runtime": "jsr:@fresh/core@^2/runtime",151+ "@fresh/plugin-vite": "jsr:@fresh/plugin-vite@^1",152+ "@preact/signals": "npm:@preact/signals@^2",153+ "preact": "npm:preact@^10",154+ "preact/hooks": "npm:preact@^10/hooks",155+ "@/": "./"156+ }157+}158+```159+160+**Adding dependencies:** Use `deno add` to add new packages:161+162+```sh163+deno add jsr:@std/http # JSR packages164+deno add npm:@tailwindcss/vite # npm packages165+```166+167+### Import Reference (Fresh 2.x)168+169+```typescript170+// Core Fresh imports171+import { App, staticFiles, fsRoutes } from "fresh";172+import { trailingSlashes, cors, csp } from "fresh";173+import { createDefine, HttpError } from "fresh";174+import type { PageProps, Middleware, RouteConfig } from "fresh";175+176+// Runtime imports (for client-side checks)177+import { IS_BROWSER } from "fresh/runtime";178+179+// Preact180+import { useSignal, signal, computed } from "@preact/signals";181+import { useState, useEffect, useRef } from "preact/hooks";182+```183+184+### Key Concepts185+186+**Routes (`routes/` folder)**187+- File-based routing: `routes/about.tsx` → `/about`188+- Dynamic routes: `routes/blog/[slug].tsx` → `/blog/my-post`189+- Optional segments: `routes/docs/[[version]].tsx` → `/docs` or `/docs/v2`190+- Catch-all routes: `routes/old/[...path].tsx` → `/old/foo/bar`191+- Route groups: `routes/(marketing)/` for shared layouts without URL path changes192+193+**Layouts (`_app.tsx`)**194+```tsx195+import type { PageProps } from "fresh";196+197+export default function App({ Component }: PageProps) {198+ return (199+ <html>200+ <head>201+ <meta charset="utf-8" />202+ <meta name="viewport" content="width=device-width, initial-scale=1" />203+ <title>My App</title>204+ </head>205+ <body>206+ <Component />207+ </body>208+ </html>209+ );210+}211+```212+213+**Async Server Components**214+```tsx215+export default async function Page() {216+ const data = await fetchData(); // Runs on server only217+ return <div>{data.title}</div>;218+}219+```220+221+## Data Fetching Patterns222+223+Fresh 2.x provides two approaches for fetching data on the server. The handler pattern is the recommended default because it demonstrates the full Fresh 2.x architecture and provides the most flexibility.224+225+### Approach A: Handler with Data Object (Recommended)226+227+Use this as the default for data fetching. It uses the full Fresh 2.x handler pattern with typed data passing. Always show the complete setup including `utils/state.ts` when demonstrating this pattern.228+229+```tsx230+// utils/state.ts - one-time setup for type-safe handlers231+import { createDefine } from "fresh";232+233+export interface State {234+ user?: { id: string; name: string };235+}236+237+export const define = createDefine<State>();238+```239+240+```tsx241+// routes/posts.tsx242+import { define } from "@/utils/state.ts";243+244+// Handler fetches data and returns it via { data: {...} }245+export const handler = define.handlers(async (ctx) => {246+ const response = await fetch("https://jsonplaceholder.typicode.com/posts");247+ const posts = await response.json();248+ return { data: { posts } };249+});250+251+// Page receives typed data252+export default define.page<typeof handler>(({ data }) => {253+ return (254+ <div>255+ <h1>Posts</h1>256+ <ul>257+ {data.posts.map((post) => <li key={post.id}>{post.title}</li>)}258+ </ul>259+ </div>260+ );261+});262+```263+264+This approach also supports auth checks, redirects, and other logic before rendering.265+266+### Approach B: Async Server Components (Shorthand)267+268+For the simplest cases where you just need to fetch and display data with no auth or redirects:269+270+```tsx271+// routes/servers.tsx272+export default async function ServersPage() {273+ const servers = await db.query("SELECT * FROM servers");274+275+ return (276+ <div>277+ <h1>Servers</h1>278+ <ul>279+ {servers.map((s) => <li key={s.id}>{s.name}</li>)}280+ </ul>281+ </div>282+ );283+}284+```285+286+### Decision Guide287+288+```289+Need to fetch data on server?290+├─ Yes → Use handler with { data: {...} } return (Approach A)291+│ (supports auth checks, redirects, and typed data passing)292+├─ Simple DB query, no logic? → Async page component is also fine (Approach B)293+└─ No → Just use a regular page component294+```295+296+## Handlers and Define Helpers (Fresh 2.x)297+298+Fresh 2.x uses a **single context parameter** pattern for handlers. Always use `(ctx)` as the only parameter.299+300+**Important:** When demonstrating any handler pattern (data fetching, form handling, API routes, auth), always show or reference the `utils/state.ts` setup which imports `createDefine` from `"fresh"`. This ensures the complete Fresh 2.x architecture is visible.301+302+### Route Handlers303+304+Always use `define.handlers()` for type-safe route handlers in file-based routes:305+306+```tsx307+// routes/api/users.ts308+import { define } from "@/utils/state.ts";309+310+// Single function handles all methods311+export const handler = define.handlers((ctx) => {312+ return new Response(`Hello from ${ctx.req.method}`);313+});314+315+// Or method-specific handlers316+export const handler = define.handlers({317+ GET(ctx) {318+ return Response.json({ users: [] });319+ },320+ async POST(ctx) {321+ const body = await ctx.req.json();322+ return Response.json({ created: true }, { status: 201 });323+ },324+});325+```326+327+Note: Bare handler exports (`export const handler = (ctx) => {...}`) also work but lose TypeScript type safety. Prefer `define.handlers()`.328+329+### The Context Object330+331+The `ctx` parameter provides everything you need:332+333+```tsx334+export const handler = (ctx) => {335+ ctx.req // The Request object336+ ctx.url // URL instance with pathname, searchParams337+ ctx.params // Route parameters { slug: "my-post" }338+ ctx.state // Request-scoped data for middlewares339+ ctx.config // Fresh configuration340+ ctx.route // Matched route pattern341+ ctx.error // Caught error (on error pages)342+343+ // Methods344+ ctx.render(<JSX />) // Render JSX to Response (JSX only, NOT data objects!)345+ ctx.render(<JSX />, { status: 201, headers: {...} }) // With response options346+ ctx.redirect("/other") // Redirect (302 default)347+ ctx.redirect("/other", 301) // Permanent redirect348+ ctx.next() // Call next middleware349+};350+```351+352+### Define Helpers (Type Safety)353+354+Create a `utils/state.ts` file for type-safe handlers:355+356+```tsx357+// utils/state.ts358+import { createDefine } from "fresh";359+360+// Define your app's state type361+export interface State {362+ user?: { id: string; name: string };363+}364+365+// Export typed define helpers366+export const define = createDefine<State>();367+```368+369+Use in routes:370+371+```tsx372+// routes/profile.tsx373+import { define } from "@/utils/state.ts";374+import type { PageProps } from "fresh";375+376+// Typed handler with data377+export const handler = define.handlers((ctx) => {378+ if (!ctx.state.user) {379+ return ctx.redirect("/login");380+ }381+ return { data: { user: ctx.state.user } };382+});383+384+// Page receives typed data385+export default define.page<typeof handler>(({ data }) => {386+ return <h1>Welcome, {data.user.name}!</h1>;387+});388+```389+390+### Middleware (Fresh 2.x)391+392+```tsx393+// routes/_middleware.ts394+import { define } from "@/utils/state.ts";395+396+export const handler = define.middleware(async (ctx) => {397+ // Before route handler398+ console.log(`${ctx.req.method} ${ctx.url.pathname}`);399+400+ // Call next middleware/route401+ const response = await ctx.next();402+403+ // After route handler404+ return response;405+});406+```407+408+### API Routes409+410+```tsx411+// routes/api/posts/[id].ts412+import { define } from "@/utils/state.ts";413+import { HttpError } from "fresh";414+415+export const handler = define.handlers({416+ async GET(ctx) {417+ const post = await getPost(ctx.params.id);418+ if (!post) {419+ throw new HttpError(404); // Uses _error.tsx420+ }421+ return Response.json(post);422+ },423+424+ async DELETE(ctx) {425+ if (!ctx.state.user) {426+ throw new HttpError(401);427+ }428+ await deletePost(ctx.params.id);429+ return new Response(null, { status: 204 });430+ },431+});432+```433+434+## Islands (Interactive Components)435+436+Islands are components that get hydrated (made interactive) on the client. Place them in the `islands/` folder or `(_islands)` folder within routes.437+438+### When to Use Islands439+440+- User interactions (clicks, form inputs)441+- Client-side state (counters, toggles)442+- Browser APIs (localStorage, geolocation)443+444+### Island Example445+446+```tsx447+// islands/Counter.tsx448+import { useSignal } from "@preact/signals";449+450+export default function Counter() {451+ const count = useSignal(0);452+453+ return (454+ <div>455+ <p>Count: {count.value}</p>456+ <button onClick={() => count.value++}>457+ Increment458+ </button>459+ </div>460+ );461+}462+```463+464+### Client-Only Code with IS_BROWSER465+466+```tsx467+// islands/LocalStorageCounter.tsx468+import { IS_BROWSER } from "fresh/runtime";469+import { useSignal } from "@preact/signals";470+471+export default function LocalStorageCounter() {472+ // Return placeholder during SSR473+ if (!IS_BROWSER) {474+ return <div>Loading...</div>;475+ }476+477+ // Client-only code478+ const stored = localStorage.getItem("count");479+ const count = useSignal(stored ? parseInt(stored) : 0);480+481+ return (482+ <button onClick={() => {483+ count.value++;484+ localStorage.setItem("count", String(count.value));485+ }}>486+ Count: {count.value}487+ </button>488+ );489+}490+```491+492+### Island Props (Serializable Types)493+494+Islands can receive these prop types:495+- Primitives: string, number, boolean, bigint, undefined, null496+- Special values: Infinity, -Infinity, NaN, -0497+- Collections: Array, Map, Set498+- Objects: Plain objects with string keys499+- Built-ins: URL, Date, RegExp, Uint8Array500+- Preact: JSX elements, Signals (with serializable values)501+- Circular references are supported502+503+**Functions cannot be passed as props.**504+505+### Island Rules506+507+1. **Props must be serializable** - No functions, only JSON-compatible data508+2. **Keep islands small** - Less JavaScript shipped to client509+3. **Prefer server components** - Only use islands when you need interactivity510+511+## Preact512+513+Preact is a 3KB alternative to React. Fresh uses Preact instead of React.514+515+### Preact vs React Differences516+517+| Preact | React |518+|--------|-------|519+| `class` works | `className` required |520+| `@preact/signals` | `useState` |521+| 3KB bundle | ~40KB bundle |522+523+### Hooks (Same as React)524+525+```tsx526+import { useState, useEffect, useRef } from "preact/hooks";527+528+function MyComponent() {529+ const [value, setValue] = useState(0);530+ const inputRef = useRef<HTMLInputElement>(null);531+532+ useEffect(() => {533+ console.log("Component mounted");534+ }, []);535+536+ return <input ref={inputRef} value={value} />;537+}538+```539+540+### Signals (Preact's Reactive State)541+542+Signals are Preact's more efficient alternative to useState:543+544+```tsx545+import { signal, computed } from "@preact/signals";546+547+const count = signal(0);548+const doubled = computed(() => count.value * 2);549+550+function Counter() {551+ return (552+ <div>553+ <p>Count: {count}</p>554+ <p>Doubled: {doubled}</p>555+ <button onClick={() => count.value++}>+1</button>556+ </div>557+ );558+}559+```560+561+Benefits of signals:562+- More granular updates (only re-renders what changed)563+- Can be defined outside components564+- Cleaner code for shared state565+566+## Tailwind CSS in Fresh (Optional)567+568+Tailwind CSS is optional—you don't need it to build a great Fresh app. However, many developers prefer it for rapid styling. Fresh 2.x uses Vite for builds, so Tailwind integrates via the Vite plugin.569+570+### Setup571+572+Install both Tailwind packages:573+574+```sh575+deno add npm:@tailwindcss/vite npm:tailwindcss576+```577+578+**Important:** You need both packages. `@tailwindcss/vite` is the Vite plugin, and `tailwindcss` is the core library it depends on.579+580+Configure Vite in `vite.config.ts`:581+```typescript582+import { defineConfig } from "vite";583+import tailwindcss from "@tailwindcss/vite";584+585+export default defineConfig({586+ plugins: [tailwindcss()],587+});588+```589+590+Add the Tailwind import to your CSS file (e.g., `assets/styles.css`):591+```css592+@import "tailwindcss";593+```594+595+Then import this CSS file in your `client.ts`:596+```typescript597+import "./assets/styles.css";598+```599+600+### Usage601+602+```tsx603+export default function Button({ children }) {604+ return (605+ <button class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">606+ {children}607+ </button>608+ );609+}610+```611+612+### Best Practices613+614+1. **Prefer utility classes** over `@apply`615+2. **Use `class` not `className`** (Preact supports both, but `class` is simpler)616+3. **Dark mode**: Use `class` strategy in tailwind.config.js617+618+```tsx619+<div class="bg-white dark:bg-gray-900">620+ <p class="text-gray-900 dark:text-white">Hello</p>621+</div>622+```623+624+## Building and Deploying625+626+### Development627+628+```bash629+deno task dev # Start dev server with hot reload (http://127.0.0.1:5173/)630+```631+632+### Production Build633+634+```bash635+deno task build # Build for production636+deno task preview # Preview production build locally637+```638+639+### Deploy to Deno Deploy640+641+```bash642+deno task build # Build first643+deno deploy --prod # Deploy to production644+```645+646+## Quick Reference647+648+| Task | Command/Pattern |649+|------|-----------------|650+| Create Fresh project | `deno run -Ar jsr:@fresh/init` |651+| Start dev server | `deno task dev` (port 5173) |652+| Build for production | `deno task build` |653+| Add a page | Create `routes/pagename.tsx` |654+| Add an API route | Create `routes/api/endpoint.ts` |655+| Add interactive component | Create `islands/ComponentName.tsx` |656+| Add static component | Create `components/ComponentName.tsx` |657+658+## Common Mistakes659+660+### Using Fresh 1.x Patterns (Most Common LLM Error)661+662+**Using old import specifiers**663+664+The old dollar-sign Fresh import paths and alpha version imports are deprecated. Always use the stable `fresh` package:665+666+```tsx667+// ✅ CORRECT - Fresh 2.x stable imports668+import { App, staticFiles } from "fresh";669+import type { PageProps } from "fresh";670+```671+672+**Using two-parameter handlers**673+674+The old two-parameter handler signature is deprecated. Fresh 2.x uses a single context parameter:675+676+```tsx677+// ✅ CORRECT - Fresh 2.x uses single context parameter678+export const handler = {679+ GET(ctx) { // Single ctx param680+ return ctx.render(<MyPage />);681+ }682+};683+```684+685+**Creating legacy files**686+687+Fresh 2.x does not use a manifest file, a separate dev entry point, or a separate config file. The correct Fresh 2.x file structure is:688+689+```690+main.ts # Server entry691+client.ts # Client entry692+vite.config.ts # Vite config693+```694+695+**Using deprecated context methods**696+697+The old `renderNotFound()`, bare `render()` without JSX, and `basePath` patterns are deprecated. Use these Fresh 2.x patterns instead:698+699+```tsx700+// ✅ CORRECT - Fresh 2.x patterns701+throw new HttpError(404)702+ctx.render(<MyComponent />)703+ctx.config.basePath704+```705+706+**Passing data from handlers to pages (VERY COMMON MISTAKE)**707+708+This is a frequent error. In Fresh 2.x, you cannot pass data through `ctx.render()`. Instead, return an object with a `data` property from the handler:709+710+```tsx711+// ✅ CORRECT - Return object with data property from handler712+export const handler = define.handlers(async (ctx) => {713+ const servers = await getServers();714+ return { data: { servers } }; // Return { data: {...} } object715+});716+717+// ✅ CORRECT - Link page to handler type with typeof718+export default define.page<typeof handler>(({ data }) => {719+ return <ul>{data.servers.map((s) => <li>{s.name}</li>)}</ul>;720+});721+722+// ✅ ALSO CORRECT - Use async page component (simpler when no auth/redirects needed)723+export default async function ServersPage() {724+ const servers = await getServers();725+ return <ul>{servers.map((s) => <li>{s.name}</li>)}</ul>;726+}727+```728+729+**Old task commands in deno.json**730+731+The old task commands that reference `dev.ts` are deprecated. Use the Vite-based tasks:732+733+```json734+// ✅ CORRECT - Fresh 2.x tasks735+{736+ "tasks": {737+ "dev": "vite",738+ "build": "vite build",739+ "preview": "deno serve -A _fresh/server.js"740+ }741+}742+```743+744+### Island Mistakes745+746+**Putting too much JavaScript in islands**747+```tsx748+// ❌ Wrong - entire page as an island (ships all JS to client)749+// islands/HomePage.tsx750+export default function HomePage() {751+ return (752+ <div>753+ <Header />754+ <MainContent />755+ <Footer />756+ </div>757+ );758+}759+760+// ✅ Correct - only interactive parts are islands761+// routes/index.tsx (server component)762+import Counter from "../islands/Counter.tsx";763+764+export default function HomePage() {765+ return (766+ <div>767+ <Header />768+ <MainContent />769+ <Counter />770+ <Footer />771+ </div>772+ );773+}774+```775+776+**Passing non-serializable props to islands**777+```tsx778+// ❌ Wrong - functions can't be serialized779+<Counter onUpdate={(val) => console.log(val)} />780+781+// ✅ Correct - only pass JSON-serializable data782+<Counter initialValue={5} label="Click count" />783+```784+785+### Other Common Mistakes786+787+**Using `className` instead of `class`**788+```tsx789+// ❌ Works but unnecessary in Preact790+<div className="container">791+792+// ✅ Preact supports native HTML attribute793+<div class="container">794+```795+796+**Forgetting to build before deploying Fresh 2.x**797+```bash798+# ❌ Wrong - Fresh 2.x requires a build step799+deno deploy --prod800+801+# ✅ Correct - build first, then deploy802+deno task build803+deno deploy --prod804+```805+806+**Creating islands for non-interactive content**807+```tsx808+// ❌ Wrong - this doesn't need to be an island (no interactivity)809+// islands/StaticCard.tsx810+export default function StaticCard({ title, body }) {811+ return <div class="card"><h2>{title}</h2><p>{body}</p></div>;812+}813+814+// ✅ Correct - use a regular component (no JS shipped)815+// components/StaticCard.tsx816+export default function StaticCard({ title, body }) {817+ return <div class="card"><h2>{title}</h2><p>{body}</p></div>;818+}819+```820+821+**Using old Tailwind plugin**822+823+The old Fresh 1.x Tailwind plugin is deprecated. Fresh 2.x uses the Vite Tailwind plugin:824+825+```typescript826+// ✅ CORRECT - Fresh 2.x uses Vite Tailwind plugin827+import tailwindcss from "@tailwindcss/vite";828+```829+830+**Missing tailwindcss package**831+```sh832+# Error: Can't resolve 'tailwindcss' in '/path/to/assets'833+834+# ❌ WRONG - Only installed the Vite plugin835+deno add npm:@tailwindcss/vite836+837+# ✅ CORRECT - Install both packages838+deno add npm:@tailwindcss/vite npm:tailwindcss839+```840+841+The `@tailwindcss/vite` plugin requires the core `tailwindcss` package to be installed separately.842+843+## Fresh Alpha Versions (2.0.0-alpha.*)844+845+Some projects use Fresh 2.x alpha releases (e.g., `@fresh/core@2.0.0-alpha.29`). These are **not Fresh 1.x** but use a different setup than stable Fresh 2.x:846+847+| Alpha pattern | Stable 2.x pattern |848+|---|---|849+| `dev.ts` entry point | `vite.config.ts` |850+| `@fresh/plugin-tailwind` | `@tailwindcss/vite` |851+| `deno run -A --watch dev.ts` | `vite` |852+| Dev server on port 8000 | Dev server on port 5173 |853+| No `client.ts` | Requires `client.ts` |854+| `deno run -A dev.ts build` | `vite build` |855+856+**IMPORTANT:** If you see `dev.ts` in a project with `@fresh/core@2.0.0-alpha.*` in `deno.json`, do NOT treat it as a Fresh 1.x artifact. It is the correct entry point for alpha versions. Check the `deno.json` imports to determine which version is in use before suggesting changes.857+858+Alpha projects also use the handler pattern `define.handlers({ GET(ctx) { ... } })` which returns `{ data: {...} }` - this is the same as stable 2.x.859+860+## Migrating from Fresh 1.x to 2.x861+862+If you have an existing Fresh 1.x project, run the migration tool:863+864+```bash865+deno run -Ar jsr:@fresh/update866+```867+868+This tool automatically:869+- Converts old import paths to the new `fresh` package870+- Updates handler signatures to use the single `(ctx)` parameter871+- Removes legacy generated and config files872+- Creates `vite.config.ts` and `client.ts`873+- Updates `deno.json` tasks to use Vite874+- Merges separate error pages into unified `_error.tsx`875+- Updates deprecated context method calls to Fresh 2.x equivalents876+877+### Manual Migration Checklist878+879+If the tool misses anything:880+881+1. **Imports**: All Fresh imports should come from `fresh` or `fresh/runtime`882+2. **Handlers**: Should use single `(ctx)` parameter, access request via `ctx.req`883+3. **Files**: Remove any legacy generated files, dev entry points, or old config files884+4. **Tasks**: Update to `vite`, `vite build`, `deno serve -A _fresh/server.js`885+5. **Error pages**: Use a single unified `_error.tsx`886+6. **Tailwind**: Use `@tailwindcss/vite` (the Vite plugin)
A .github/skills/deno-guidance/SKILL.md +239 -0
@@ -0,0 +1,239 @@
1+---2+name: deno-guidance3+description: Use when starting any Deno project, choosing packages, configuring deno.json, or running CLI commands. Provides foundational knowledge for building modern Deno applications.4+license: MIT5+metadata:6+ author: denoland7+ version: "1.2"8+---9+10+# Deno Development Guidance11+12+## Overview13+14+This skill provides foundational knowledge for building modern Deno applications. Deno is a secure JavaScript/TypeScript runtime that runs TypeScript directly, has built-in tools (formatter, linter, test runner), and uses modern package management through JSR.15+16+## When to Use This Skill17+18+- Starting a new Deno project19+- Adding dependencies to a project20+- Configuring `deno.json` settings21+- Running Deno CLI commands (fmt, lint, test)22+- Setting up import maps23+- Understanding Deno's permission system24+25+Apply these practices whenever working in a Deno project (identified by the presence of `deno.json`).26+27+## Scope Boundaries28+29+This skill applies **only** to Deno-specific questions. Follow these rules:30+31+- If the user asks about **Node.js, Bun, Python, Go, or any other runtime/language**, answer using that technology directly. Do not suggest Deno alternatives or include Deno-specific patterns.32+- Do not include `jsr:` imports, `deno add`, or `deno.json` configuration in responses about other technologies.33+- For **generic TypeScript/JavaScript questions** not tied to a specific runtime, give a general answer without assuming Deno.34+- Only recommend Deno when the user explicitly asks about Deno or is working in a Deno project.35+36+## CRITICAL: Never Show Deprecated Syntax37+38+When helping users migrate from deprecated patterns, describe the old approach generically and ONLY show the correct modern code. Never write out actual deprecated URLs or import paths, even in "before/after" comparisons. The string `deno.land/x/` must never appear in your response, in any context.39+40+- Say "Replace your old URL-based imports with JSR imports" — then show only the correct `jsr:` approach41+- Say "the old URL-based registry" or "the old standard library URL" — do NOT write the actual deprecated URL42+- Even if the user writes a deprecated URL in their question, do NOT echo it back. Refer to it generically.43+44+Only demonstrate the correct, current approach.45+46+## Package Management Priority47+48+When adding dependencies, follow this priority order:49+50+1. **JSR packages (`jsr:`)** - Preferred for Deno-native packages51+ - Better TypeScript support (types are built-in)52+ - Faster to resolve and install53+ - Example: `jsr:@std/http`, `jsr:@fresh/core`54+55+2. **npm packages (`npm:`)** - Fully supported, use when no JSR alternative exists56+ - Deno has full npm compatibility57+ - Example: `npm:express`, `npm:zod`58+59+3. **AVOID: Old URL-based imports** - Deprecated registry60+ - The old URL-based package registry is deprecated61+ - Many LLMs incorrectly default to URL-based imports62+ - Always use `jsr:` instead63+64+### Standard Library65+66+The Deno standard library lives at `@std/` on JSR:67+68+```jsonc69+// deno.json70+{71+ "imports": {72+ "@std/assert": "jsr:@std/assert@1",73+ "@std/http": "jsr:@std/http@1",74+ "@std/path": "jsr:@std/path@1"75+ }76+}77+```78+79+```typescript80+import { serve } from "@std/http";81+import { join } from "@std/path";82+import { assertEquals } from "@std/assert";83+```84+85+Always use `jsr:@std/*` for the standard library (the old URL-based imports are deprecated).86+87+## Understanding Deno88+89+Reference: https://docs.deno.com/runtime/fundamentals/90+91+Key concepts:92+- **Native TypeScript** - No build step needed, Deno runs TypeScript directly93+- **Explicit permissions** - Use flags like `--allow-net`, `--allow-read`, `--allow-env`94+- **deno.json** - The config file (similar to package.json but simpler)95+- **Import maps** - Define import aliases in deno.json's `imports` field96+97+## Workflow Best Practices98+99+### After Making Code Changes100+101+Run these commands regularly, especially after significant changes:102+103+```bash104+deno fmt # Format all files105+deno lint # Check for issues106+deno test # Run tests107+```108+109+### Package Management110+111+```bash112+deno add jsr:@std/http # Add a package113+deno install # Install all dependencies114+deno update # Update all dependencies to latest compatible versions115+deno update jsr:@std/http # Update a specific dependency116+```117+118+**`deno update` vs `deno upgrade`:**119+120+- `deno update` - Updates **project dependencies** in `deno.json` (and `package.json`) to their latest compatible versions. Respects semver ranges. Use this to keep your dependencies current.121+- `deno upgrade` - Updates the **Deno runtime itself** to the latest version. Has nothing to do with project dependencies.122+123+After running `deno update`, always check for breaking API changes - especially for alpha/pre-release packages where semver ranges can pull in breaking updates.124+125+126+### CI/CD127+128+In CI pipelines, use `--check` with `deno fmt` so it fails without modifying files:129+130+```bash131+deno fmt --check # Fail if not formatted132+deno lint # Check for issues133+deno test # Run tests134+```135+136+### Configuration137+138+In `deno.json`, you can exclude directories from formatting/linting:139+140+```json141+{142+ "fmt": {143+ "exclude": ["build/"]144+ },145+ "lint": {146+ "exclude": ["build/"]147+ }148+}149+```150+151+A folder can also be excluded from everything at the top level:152+153+```json154+{155+ "exclude": ["build/"]156+}157+```158+159+## Deployment160+161+For deploying to Deno Deploy, see the dedicated **deno-deploy** skill.162+163+Quick command: `deno deploy --prod`164+165+## Documentation Resources166+167+When more information is needed:168+169+- **`deno doc <package>`** - Generate docs for any JSR or npm package locally170+- **https://docs.deno.com** - Official Deno documentation171+- **https://jsr.io** - Package registry with built-in documentation172+- **https://fresh.deno.dev/docs** - Fresh framework documentation173+174+## Quick Reference: Deno CLI Commands175+176+| Command | Purpose |177+|---------|---------|178+| `deno run file.ts` | Run a TypeScript/JavaScript file |179+| `deno task <name>` | Run a task from deno.json |180+| `deno fmt` | Format code |181+| `deno lint` | Lint code |182+| `deno test` | Run tests |183+| `deno add <pkg>` | Add a package |184+| `deno install` | Install dependencies |185+| `deno update` | Update project dependencies |186+| `deno upgrade` | Update Deno runtime itself |187+| `deno doc <pkg>` | View package documentation |188+| `deno deploy --prod` | Deploy to Deno Deploy |189+190+## Common Mistakes191+192+**Using old URL-based imports instead of JSR**193+194+The old URL-based imports are deprecated. Always use `jsr:` imports with bare specifiers instead.195+196+```ts197+// ✅ Correct - use JSR and a bare specifier198+import { serve } from "@std/http";199+import { join } from "@std/path";200+```201+202+```jsonc203+// deno.json204+{205+ "imports": {206+ "@std/http": "jsr:@std/http@1",207+ "@std/path": "jsr:@std/path@1"208+ }209+}210+```211+212+Inline specifiers are fine in single file scripts, but if a deno.json exists then it should go there. It's preferable to place npm dependencies in a package.json if a package.json exists.213+214+**Forgetting to run fmt/lint before committing**215+216+Always format and lint before committing:217+218+```bash219+# ✅ Always format and lint first220+deno fmt && deno lint && git add . && git commit -m "changes"221+```222+223+**Running code without permission flags**224+225+```bash226+# ✅ Grant specific permissions227+deno run --allow-net server.ts228+```229+230+Without permission flags, Deno will show "Requires net access" errors. Always grant the specific permissions your code needs.231+232+**Not using `deno add` for dependencies**233+234+```bash235+# ✅ Use deno add to manage dependencies236+deno add jsr:@std/http237+```238+239+Using `deno add` ensures your lockfile stays in sync. Manually editing imports without updating deno.json works but misses lockfile benefits.
A .github/skills/deno-project-templates/SKILL.md +258 -0
@@ -0,0 +1,258 @@
1+---2+name: deno-project-templates3+description: Use when scaffolding new Deno projects. Provides templates for Fresh web apps, CLI tools, libraries, and API servers with modern best practices.4+license: MIT5+metadata:6+ author: denoland7+ version: "1.2"8+---9+10+# Deno Project Templates11+12+This skill provides templates for creating new Deno projects with modern best practices.13+14+## When to Use This Skill15+16+- Creating a new Deno project from scratch17+- Setting up project structure for different application types18+- Scaffolding Fresh web apps, CLI tools, libraries, or API servers19+20+## Scope Boundaries21+22+This skill applies **only** when the user asks for a Deno project. Follow these rules:23+24+- If the user asks for a **Node.js, Python, Go, Rust, or other non-Deno project**, answer using that technology's project setup directly. Do not suggest Deno templates.25+- Only use these templates when the user explicitly asks for a Deno project or is working in a Deno environment.26+- When mentioning deprecated patterns, describe them generically. Do not write out deprecated URLs or import syntax — only show the correct modern approach.27+28+## Project Types29+30+Choose the appropriate template based on what you want to build:31+32+| Type | Use Case | Key Files |33+|------|----------|-----------|34+| **Fresh web app** | Full-stack web application with Fresh framework | `main.ts`, `routes/`, `islands/` |35+| **CLI tool** | Command-line application | `main.ts` with arg parsing |36+| **Library** | Reusable package to publish on JSR | `mod.ts`, `mod_test.ts` |37+| **API server** | Backend API without frontend | `main.ts` with HTTP handlers |38+39+## Fresh Web App40+41+For full-stack web applications, use the Fresh initializer:42+43+```bash44+deno run -Ar jsr:@fresh/init my-project45+cd my-project46+```47+48+This creates:49+- `deno.json` - Project configuration and dependencies50+- `main.ts` - Server entry point51+- `client.ts` - Client entry point (CSS imports)52+- `vite.config.ts` - Vite build configuration53+- `routes/` - Pages and API routes (file-based routing)54+- `islands/` - Interactive components that get JavaScript on the client55+- `components/` - Server-only components (no JavaScript shipped)56+- `static/` - Static assets like images, CSS57+58+**Development:** Fresh uses Vite. The dev server runs at `http://localhost:5173` (not port 8000).59+60+```bash61+deno task dev62+```63+64+## CLI Tool65+66+Create a command-line application with argument parsing.67+68+**Template files:** See `assets/cli-tool/` directory.69+70+### deno.json71+72+```json73+{74+ "name": "my-cli",75+ "version": "0.1.0",76+ "exports": "./main.ts",77+ "tasks": {78+ "dev": "deno run --allow-all main.ts",79+ "compile": "deno compile --allow-all -o my-cli main.ts"80+ },81+ "imports": {82+ "@std/cli": "jsr:@std/cli@^1",83+ "@std/fmt": "jsr:@std/fmt@^1"84+ }85+}86+```87+88+### main.ts89+90+```typescript91+import { parseArgs } from "@std/cli/parse-args";92+import { bold, green } from "@std/fmt/colors";93+94+const args = parseArgs(Deno.args, {95+ boolean: ["help", "version"],96+ alias: { h: "help", v: "version" },97+});98+99+if (args.help) {100+ console.log(`101+${bold("my-cli")} - A Deno CLI tool102+103+${bold("USAGE:")}104+ my-cli [OPTIONS]105+106+${bold("OPTIONS:")}107+ -h, --help Show this help message108+ -v, --version Show version109+`);110+ Deno.exit(0);111+}112+113+if (args.version) {114+ console.log("my-cli v0.1.0");115+ Deno.exit(0);116+}117+118+console.log(green("Hello from my-cli"));119+```120+121+## Library122+123+Create a reusable package for publishing to JSR.124+125+**Template files:** See `assets/library/` directory.126+127+### deno.json128+129+```json130+{131+ "name": "@username/my-library",132+ "version": "0.1.0",133+ "exports": "./mod.ts",134+ "tasks": {135+ "test": "deno test",136+ "check": "deno check mod.ts",137+ "publish": "deno publish"138+ }139+}140+```141+142+### mod.ts143+144+```typescript145+/**146+ * my-library - A Deno library147+ *148+ * @module149+ */150+151+/**152+ * Example function - replace with your library's functionality153+ *154+ * @param name The name to greet155+ * @returns A greeting message156+ *157+ * @example158+ * ```ts159+ * import { greet } from "@username/my-library";160+ * console.log(greet("World")); // "Hello, World"161+ * ```162+ */163+export function greet(name: string): string {164+ return `Hello, ${name}`;165+}166+```167+168+### mod_test.ts169+170+```typescript171+import { assertEquals } from "jsr:@std/assert";172+import { greet } from "./mod.ts";173+174+Deno.test("greet returns correct message", () => {175+ assertEquals(greet("World"), "Hello, World");176+});177+```178+179+**Remember:** Replace `@username` with your JSR username before publishing.180+181+## API Server182+183+Create a backend API without a frontend.184+185+**Template files:** See `assets/api-server/` directory.186+187+### deno.json188+189+```json190+{191+ "tasks": {192+ "dev": "deno run --watch --allow-net main.ts",193+ "start": "deno run --allow-net main.ts"194+ },195+ "imports": {196+ "@std/http": "jsr:@std/http@^1"197+ }198+}199+```200+201+### main.ts202+203+```typescript204+import { serve } from "@std/http";205+206+const handler = (request: Request): Response => {207+ const url = new URL(request.url);208+209+ if (url.pathname === "/") {210+ return new Response("Welcome to the API", {211+ headers: { "Content-Type": "text/plain" },212+ });213+ }214+215+ if (url.pathname === "/api/hello") {216+ return Response.json({ message: "Hello from Deno" });217+ }218+219+ return new Response("Not Found", { status: 404 });220+};221+222+console.log("Server running at http://localhost:8000");223+serve(handler, { port: 8000 });224+```225+226+## Post-Setup Steps227+228+After creating project files:229+230+```bash231+cd my-project232+deno install # Install dependencies233+deno fmt # Format the code234+deno lint # Check for issues235+```236+237+## Development Commands by Project Type238+239+| Project Type | Start Development | Build/Compile |240+|--------------|-------------------|---------------|241+| Fresh | `deno task dev` (port 5173) | `deno task build` |242+| CLI | `deno task dev` | `deno task compile` |243+| Library | `deno test` | N/A |244+| API | `deno task dev` | N/A |245+246+## Deployment247+248+When ready to deploy:249+- Fresh: `deno task build && deno deploy --prod`250+- CLI: `deno task compile` (creates standalone binary)251+- Library: `deno publish` (publishes to JSR)252+- API: `deno deploy --prod`253+254+## Best Practices255+256+- Always use `jsr:` imports for Deno packages (the old URL-based imports are deprecated)257+- Run `deno fmt` and `deno lint` regularly258+- Projects are configured for Deno Deploy compatibility
A .github/skills/deno-project-templates/assets/api-server/deno.json +9 -0
A .github/skills/deno-project-templates/assets/api-server/main.ts +20 -0
A .github/skills/deno-project-templates/assets/cli-tool/deno.json +13 -0
A .github/skills/deno-project-templates/assets/cli-tool/main.ts +28 -0
A .github/skills/deno-project-templates/assets/fresh-app/README.md +33 -0
A .github/skills/deno-project-templates/assets/library/deno.json +10 -0
A .github/skills/deno-project-templates/assets/library/mod.ts +21 -0
A .github/skills/deno-project-templates/assets/library/mod_test.ts +6 -0
A .github/skills/deno-sandbox/SKILL.md +395 -0
@@ -0,0 +1,395 @@
1+---2+name: deno-sandbox3+description: Use when building features that execute untrusted user code, AI-generated code, or need isolated code execution environments. Covers the @deno/sandbox SDK.4+license: MIT5+metadata:6+ author: denoland7+ version: "1.1"8+---9+10+# Deno Sandboxes11+12+## Overview13+14+Deno Sandboxes provide secure, isolated environments for running untrusted code. Each sandbox runs in its own Linux microVM (using Firecracker, the same technology as AWS Lambda) with a separate filesystem, network, and process space. This makes them ideal for code playgrounds, AI agent tool execution, and multi-tenant applications.15+16+Reference: https://deno.com/deploy/sandboxes17+18+## When to Use Sandboxes19+20+Use Deno Sandboxes when you need to:21+22+- Run user-submitted code safely23+- Execute AI-generated code24+- Build code playground platforms25+- Create multi-tenant code execution environments26+- Run automated tests in isolation27+28+## Scope Boundaries29+30+This skill applies **only** to Deno Sandbox (`@deno/sandbox`) questions. Follow these rules:31+32+- If the user asks about **Docker containers, Node.js vm2/vm, Web Workers, AWS Lambda isolation, or any other isolation technology**, answer using that technology directly. Do not suggest Deno Sandboxes as an alternative.33+- Do not include `@deno/sandbox` imports, `Sandbox.create()`, or `sandbox.spawn()` in responses about other isolation technologies.34+- Only recommend Deno Sandboxes when the user explicitly asks about them or is building code execution features in a Deno project.35+36+## Getting Started37+38+### Installation39+40+```bash41+deno add jsr:@deno/sandbox42+```43+44+### Basic Usage45+46+```typescript47+import { Sandbox } from "@deno/sandbox";48+49+// Create a sandbox (auto-disposed when scope ends)50+await using sandbox = await Sandbox.create();51+52+// Run a command53+const child = await sandbox.spawn("echo", { args: ["Hello from sandbox!"] });54+const output = await child.output();55+56+console.log(new TextDecoder().decode(output.stdout));57+// Output: Hello from sandbox!58+```59+60+## Core Concepts61+62+### Sandbox Lifecycle63+64+Sandboxes are resources that must be disposed when done. **Always** use `await using` for automatic cleanup:65+66+```typescript67+await using sandbox = await Sandbox.create();68+// Sandbox is automatically destroyed when this scope ends69+```70+71+CRITICAL: Never show `const sandbox = await Sandbox.create()` without `await using`. Always use the `await using` pattern for sandbox creation. Do not show manual disposal alternatives.72+73+### Running Processes74+75+The `spawn` method runs commands inside the sandbox:76+77+```typescript78+const child = await sandbox.spawn("deno", {79+ args: ["run", "script.ts"],80+ stdin: "piped", // Enable stdin81+ stdout: "piped", // Capture stdout82+ stderr: "piped" // Capture stderr83+});84+85+// Wait for completion and get output86+const output = await child.output();87+console.log("Exit code:", output.code);88+console.log("Stdout:", new TextDecoder().decode(output.stdout));89+console.log("Stderr:", new TextDecoder().decode(output.stderr));90+```91+92+### Streaming I/O93+94+For interactive processes or long-running commands:95+96+```typescript97+const child = await sandbox.spawn("deno", {98+ args: ["repl"],99+ stdin: "piped",100+ stdout: "piped"101+});102+103+// Write to stdin104+const writer = child.stdin!.getWriter();105+await writer.write(new TextEncoder().encode("console.log('Hello')\n"));106+await writer.close();107+108+// Read from stdout109+const reader = child.stdout!.getReader();110+while (true) {111+ const { done, value } = await reader.read();112+ if (done) break;113+ console.log(new TextDecoder().decode(value));114+}115+```116+117+### Killing Processes118+119+```typescript120+const child = await sandbox.spawn("sleep", { args: ["60"] });121+122+// Kill with SIGTERM (default)123+await child.kill();124+125+// Or with specific signal126+await child.kill("SIGKILL");127+128+// Wait for exit129+const status = await child.status;130+console.log("Exited with signal:", status.signal);131+```132+133+## Common Patterns134+135+### Running User Code Safely136+137+```typescript138+import { Sandbox } from "@deno/sandbox";139+140+async function runUserCode(code: string): Promise<string> {141+ await using sandbox = await Sandbox.create();142+143+ // Write user code to a file in the sandbox144+ await sandbox.fs.writeFile("/tmp/user_code.ts", code);145+146+ // Run with restricted permissions147+ const child = await sandbox.spawn("deno", {148+ args: [149+ "run",150+ "--allow-none", // No permissions151+ "/tmp/user_code.ts"152+ ],153+ stdout: "piped",154+ stderr: "piped"155+ });156+157+ const output = await child.output();158+159+ if (output.code !== 0) {160+ throw new Error(new TextDecoder().decode(output.stderr));161+ }162+163+ return new TextDecoder().decode(output.stdout);164+}165+```166+167+### Code Playground168+169+```typescript170+import { Sandbox } from "@deno/sandbox";171+172+interface ExecutionResult {173+ success: boolean;174+ output: string;175+ error?: string;176+ executionTime: number;177+}178+179+async function executePlayground(code: string): Promise<ExecutionResult> {180+ const start = performance.now();181+182+ await using sandbox = await Sandbox.create();183+184+ await sandbox.fs.writeFile("/playground/main.ts", code);185+186+ const child = await sandbox.spawn("deno", {187+ args: ["run", "--allow-net", "/playground/main.ts"],188+ stdout: "piped",189+ stderr: "piped"190+ });191+192+ const output = await child.output();193+ const executionTime = performance.now() - start;194+195+ return {196+ success: output.code === 0,197+ output: new TextDecoder().decode(output.stdout),198+ error: output.code !== 0 ? new TextDecoder().decode(output.stderr) : undefined,199+ executionTime200+ };201+}202+```203+204+### AI Agent Tool Execution205+206+```typescript207+import { Sandbox } from "@deno/sandbox";208+209+async function executeAgentTool(toolCode: string, input: unknown): Promise<unknown> {210+ await using sandbox = await Sandbox.create();211+212+ // Create a wrapper that handles input/output213+ const wrapper = `214+ const input = ${JSON.stringify(input)};215+ const tool = await import("/tool.ts");216+ const result = await tool.default(input);217+ console.log(JSON.stringify(result));218+ `;219+220+ await sandbox.fs.writeFile("/tool.ts", toolCode);221+ await sandbox.fs.writeFile("/run.ts", wrapper);222+223+ const child = await sandbox.spawn("deno", {224+ args: ["run", "--allow-net", "/run.ts"],225+ stdout: "piped",226+ stderr: "piped"227+ });228+229+ const output = await child.output();230+231+ if (output.code !== 0) {232+ throw new Error(new TextDecoder().decode(output.stderr));233+ }234+235+ return JSON.parse(new TextDecoder().decode(output.stdout));236+}237+```238+239+## Sandbox Features240+241+### Resource Configuration242+243+Sandboxes have configurable resources:244+245+- **Default:** 2 vCPUs, 512MB memory, 10GB disk246+- Startup time: Under 200ms247+248+### What's Included249+250+Each sandbox comes with:251+252+- TypeScript/JavaScript runtime (Deno)253+- Full Linux environment254+- Network access (can be restricted)255+- Temporary filesystem256+257+### Security Features258+259+- **Firecracker microVMs** - Same technology as AWS Lambda260+- **Full isolation** - Separate kernel, filesystem, network261+- **No data leakage** - Sandboxes can't access host system262+- **Enforced policies** - Control outbound connections263+264+## Deploying Sandboxes265+266+Sandboxes can be deployed directly to Deno Deploy:267+268+```bash269+deno deploy --prod270+```271+272+The sandbox SDK works seamlessly in the Deno Deploy environment.273+274+## API Reference275+276+For the complete API, run:277+278+```bash279+deno doc jsr:@deno/sandbox280+```281+282+Key classes:283+284+- `Sandbox` - Main class for creating/managing sandboxes285+- `ChildProcess` - Represents a running process286+- `Client` - For managing Deploy resources (apps, volumes)287+288+## Quick Reference289+290+| Task | Code |291+| -------------- | ---------------------------------------------- |292+| Create sandbox | `await using sandbox = await Sandbox.create()` |293+| Run command | `sandbox.spawn("cmd", { args: [...] })` |294+| Get output | `const output = await child.output()` |295+| Write file | `await sandbox.fs.writeFile(path, content)` |296+| Read file | `await sandbox.fs.readFile(path)` |297+| Kill process | `await child.kill()` |298+| Check status | `const status = await child.status` |299+300+## Common Mistakes301+302+**Forgetting automatic disposal**303+304+```typescript305+// ❌ Wrong - always use "await using" for sandbox creation306+// Never write: const sandbox = await Sandbox.create() without "await using"307+308+// ✅ Correct - use "await using" for automatic cleanup309+await using sandbox = await Sandbox.create();310+await sandbox.spawn("echo", { args: ["hello"] });311+// sandbox automatically disposed when scope ends312+```313+314+**Giving user code too many permissions**315+316+```typescript317+// ❌ Wrong - gives untrusted code full access318+const child = await sandbox.spawn("deno", {319+ args: ["run", "--allow-all", "/tmp/user_code.ts"]320+});321+322+// ✅ Correct - restrict permissions to what's needed323+const child = await sandbox.spawn("deno", {324+ args: ["run", "--allow-none", "/tmp/user_code.ts"] // No permissions325+});326+327+// Or if network is truly needed:328+const child = await sandbox.spawn("deno", {329+ args: ["run", "--allow-net", "/tmp/user_code.ts"] // Only network330+});331+```332+333+**Not handling process output properly**334+335+```typescript336+// ❌ Wrong - forgetting to pipe stdout/stderr337+const child = await sandbox.spawn("deno", { args: ["run", "script.ts"] });338+const output = await child.output();339+// output.stdout is empty because we didn't pipe it!340+341+// ✅ Correct - pipe the streams you need342+const child = await sandbox.spawn("deno", {343+ args: ["run", "script.ts"],344+ stdout: "piped",345+ stderr: "piped"346+});347+const output = await child.output();348+console.log(new TextDecoder().decode(output.stdout));349+```350+351+**Not setting timeouts for user code execution**352+353+```typescript354+// ❌ Wrong - user code could run forever355+const child = await sandbox.spawn("deno", {356+ args: ["run", "/tmp/user_code.ts"]357+});358+await child.output(); // Could hang indefinitely359+360+// ✅ Correct - implement timeout handling361+const child = await sandbox.spawn("deno", {362+ args: ["run", "/tmp/user_code.ts"],363+ stdout: "piped",364+ stderr: "piped"365+});366+367+// Set a timeout to kill the process368+const timeoutId = setTimeout(() => child.kill(), 5000); // 5 second limit369+370+try {371+ const output = await child.output();372+ return output;373+} finally {374+ clearTimeout(timeoutId);375+}376+```377+378+**Trusting sandbox output without validation**379+380+```typescript381+// ❌ Wrong - directly using untrusted output as code382+const result = await runUserCode(code);383+// Never execute or inject untrusted output!384+385+// ✅ Correct - validate and sanitize output386+const result = await runUserCode(code);387+try {388+ const parsed = JSON.parse(result); // Parse as data, not code389+ if (isValidResponse(parsed)) {390+ return parsed;391+ }392+} catch {393+ throw new Error("Invalid response from sandbox");394+}395+```
A .gitignore +15 -0
A README.md +17 -0
A assets/styles.css +788 -0
@@ -0,0 +1,788 @@
1+*,2+*::before,3+*::after {4+ box-sizing: border-box;5+}6+* {7+ margin: 0;8+}9+button {10+ color: inherit;11+}12+button, [role="button"] {13+ cursor: pointer;14+}15+code {16+ font-family:17+ ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",18+ "Courier New", monospace;19+ font-size: 1em;20+}21+img,22+svg {23+ display: block;24+}25+img,26+video {27+ max-width: 100%;28+ height: auto;29+}30+31+html {32+ line-height: 1.5;33+ -webkit-text-size-adjust: 100%;34+ font-family:35+ ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",36+ Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif,37+ "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol",38+ "Noto Color Emoji";39+ background: #f7f4ea;40+ overscroll-behavior-x: none;41+ overflow-x: hidden;42+}43+44+body {45+ min-height: 100dvh;46+ background: #f7f4ea;47+ overscroll-behavior-x: none;48+ overflow-x: hidden;49+}50+51+button,52+input,53+textarea,54+select {55+ font: inherit;56+}57+58+.shikaku-home {59+ min-height: 100dvh;60+ height: 100dvh;61+ width: 100vw;62+ overflow: hidden;63+ background: linear-gradient(180deg, #0f180d 0%, #122411 44%, #0b130b 100%);64+ color: #f7f0d8;65+ font-family:66+ ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",67+ "Courier New", monospace;68+}69+70+.shikaku-home__frame {71+ width: min(100%, 76rem);72+ height: 100%;73+ margin: 0 auto;74+ display: grid;75+ grid-template-rows: auto 1fr;76+ gap: 0.8rem;77+ padding: max(0.75rem, env(safe-area-inset-top)) 0.75rem78+ max(0.75rem, env(safe-area-inset-bottom));79+}80+81+.shikaku-home__masthead,82+.shikaku-home__hero {83+ border: 2px solid #0b1209;84+ background: #f4ebcf;85+ color: #11160d;86+ box-shadow: 6px 6px 0 #0b1209;87+}88+89+.shikaku-home__masthead {90+ display: flex;91+ align-items: center;92+ justify-content: flex-start;93+ gap: 1rem;94+ padding: 0.75rem 0.9rem;95+}96+97+.shikaku-home__brand {98+ font-size: 0.92rem;99+ font-weight: 900;100+ letter-spacing: 0.08em;101+ text-transform: uppercase;102+}103+104+.shikaku-home__hero {105+ position: relative;106+ overflow: hidden;107+ display: grid;108+ grid-template-columns: 1fr;109+ gap: 0.9rem;110+ min-height: 0;111+ height: 100%;112+ padding: 0.9rem;113+ background: linear-gradient(180deg, #efe5c2 0%, #dfe6b4 100%);114+}115+116+.shikaku-home__hero-copy {117+ position: relative;118+ z-index: 1;119+ display: grid;120+ gap: 0.85rem;121+}122+123+.shikaku-home__eyebrow,124+.shikaku-home__feature-index,125+.shikaku-home__action-kicker {126+ font-size: 0.78rem;127+ font-weight: 900;128+ letter-spacing: 0.08em;129+ text-transform: uppercase;130+}131+132+.shikaku-home__eyebrow {133+ display: inline-flex;134+ justify-self: start;135+ padding: 0.45rem 0.6rem;136+ border: 2px solid #0b1209;137+ background: #d4deb0;138+ box-shadow: 3px 3px 0 #0b1209;139+}140+141+.shikaku-home__title {142+ max-width: 8ch;143+ font-size: clamp(2.6rem, 14vw, 6.6rem);144+ line-height: 0.85;145+ letter-spacing: 0.04em;146+ text-transform: uppercase;147+ color: #f8f3de;148+ text-shadow:149+ 2px 0 0 #0b1209,150+ -2px 0 0 #0b1209,151+ 0 2px 0 #0b1209,152+ 0 -2px 0 #0b1209,153+ 6px 6px 0 #3e5f33;154+}155+156+.shikaku-home__speech-stack {157+ display: grid;158+ gap: 0.5rem;159+}160+161+.shikaku-home__speech {162+ width: fit-content;163+ max-width: min(100%, 18rem);164+ padding: 0.65rem 0.8rem;165+ border: 2px solid #0b1209;166+ background: #faf5df;167+ font-size: 0.95rem;168+ line-height: 1.3;169+ box-shadow: 4px 4px 0 #0b1209;170+}171+172+.shikaku-home__speech--accent {173+ background: #bbd083;174+}175+176+.shikaku-home__actions {177+ display: grid;178+ grid-template-columns: 1fr;179+ gap: 0.75rem;180+ margin-top: 0.2rem;181+}182+183+.shikaku-home__action {184+ display: grid;185+ gap: 0.18rem;186+ align-content: center;187+ min-height: 4rem;188+ padding: 0.8rem 0.95rem;189+ border: 2px solid #0b1209;190+ text-decoration: none;191+ color: #11160d;192+ box-shadow: 4px 4px 0 #0b1209;193+}194+195+.shikaku-home__action strong,196+.shikaku-home__feature-card strong {197+ font-size: 1rem;198+ text-transform: uppercase;199+}200+201+.shikaku-home__action--gold {202+ background: #f2cb55;203+}204+205+.shikaku-home__action--ghost {206+ background: #e2ecc0;207+}208+209+.shikaku-home__hero-art {210+ position: relative;211+ min-height: 16rem;212+ border: 2px solid #0b1209;213+ background: linear-gradient(214+ 180deg,215+ #7892d5 0 26%,216+ #5e7ac4 26% 42%,217+ #23301f 42% 100%218+ );219+ overflow: hidden;220+ box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.08);221+}222+223+.shikaku-home__sky,224+.shikaku-home__lawn-grid,225+.shikaku-home__keep,226+.shikaku-home__moon {227+ position: absolute;228+}229+230+.shikaku-home__sky {231+ inset: 0;232+ background:233+ radial-gradient(234+ circle at 18% 20%,235+ rgba(255, 245, 182, 0.45) 0 7%,236+ transparent 8%237+ ),238+ radial-gradient(239+ circle at 76% 14%,240+ rgba(255, 255, 255, 0.35) 0 4%,241+ transparent 5%242+ ),243+ radial-gradient(244+ circle at 68% 26%,245+ rgba(255, 255, 255, 0.2) 0 3%,246+ transparent 4%247+ ),248+ linear-gradient(180deg, rgba(255, 255, 255, 0.1), transparent 45%);249+}250+251+.shikaku-home__moon {252+ top: 1.2rem;253+ right: 1.3rem;254+ width: 3.3rem;255+ aspect-ratio: 1;256+ background: #f6efc9;257+ box-shadow: 0 0 0 2px #0b1209, 4px 4px 0 rgba(11, 18, 9, 0.9);258+}259+260+.shikaku-home__keep {261+ left: 50%;262+ bottom: 3.25rem;263+ width: min(86%, 20rem);264+ height: 9rem;265+ transform: translateX(-50%);266+}267+268+.shikaku-home__keep-tower,269+.shikaku-home__keep-wall,270+.shikaku-home__keep-gate,271+.shikaku-home__banner {272+ position: absolute;273+ border: 2px solid #0b1209;274+}275+276+.shikaku-home__keep-tower,277+.shikaku-home__keep-wall {278+ background: #7a7a81;279+ box-shadow: inset 0 -12px 0 rgba(0, 0, 0, 0.16);280+}281+282+.shikaku-home__keep-tower::before,283+.shikaku-home__keep-wall::before {284+ content: "";285+ position: absolute;286+ inset: 0;287+ background: linear-gradient(288+ 90deg,289+ transparent 0 18%,290+ rgba(255, 255, 255, 0.18) 18% 26%,291+ transparent 26% 100%292+ );293+}294+295+.shikaku-home__keep-tower--left {296+ left: 0;297+ bottom: 0;298+ width: 3.25rem;299+ height: 6rem;300+}301+302+.shikaku-home__keep-tower--center {303+ left: 50%;304+ bottom: 0;305+ width: 4.2rem;306+ height: 8rem;307+ transform: translateX(-50%);308+}309+310+.shikaku-home__keep-tower--right {311+ right: 0;312+ bottom: 0;313+ width: 3.25rem;314+ height: 6.5rem;315+}316+317+.shikaku-home__keep-wall {318+ left: 2.9rem;319+ right: 2.9rem;320+ bottom: 0;321+ height: 4.25rem;322+}323+324+.shikaku-home__keep-gate {325+ left: 50%;326+ bottom: 0;327+ width: 3rem;328+ height: 2.7rem;329+ transform: translateX(-50%);330+ background: #171d14;331+}332+333+.shikaku-home__banner {334+ top: 1.4rem;335+ width: 1.6rem;336+ height: 2.1rem;337+ display: grid;338+ place-items: center;339+ background: #f2cb55;340+ color: #11160d;341+ font-size: 0.92rem;342+ font-weight: 900;343+}344+345+.shikaku-home__banner--left {346+ left: 3.5rem;347+}348+349+.shikaku-home__banner--right {350+ right: 3.5rem;351+}352+353+.shikaku-home__lawn-grid {354+ left: 0;355+ right: 0;356+ bottom: 0;357+ height: 4.4rem;358+ background:359+ repeating-linear-gradient(90deg, #426231 0 0.9rem, #4e7138 0.9rem 1.8rem),360+ repeating-linear-gradient(361+ 0deg,362+ rgba(255, 255, 255, 0.08) 0 2px,363+ transparent 2px 1.15rem364+ );365+ border-top: 2px solid #0b1209;366+}367+368+.shikaku-home__feature-strip {369+ display: grid;370+ grid-template-columns: 1fr;371+ gap: 0.75rem;372+ padding: 1rem;373+ background: #1a2515;374+ color: #f7f0d8;375+}376+377+.shikaku-home__feature-card {378+ display: grid;379+ gap: 0.35rem;380+ place-items: start;381+ padding: 0.9rem;382+ border: 2px solid #cad8a0;383+ background: #24341d;384+ box-shadow: 4px 4px 0 #0b1209;385+}386+387+@media (min-width: 760px) {388+ .shikaku-home__hero {389+ grid-template-columns: minmax(0, 1.02fr) minmax(18rem, 0.98fr);390+ align-items: stretch;391+ padding: 1.35rem;392+ }393+394+ .shikaku-home__actions,395+ .shikaku-home__feature-strip {396+ grid-template-columns: repeat(2, minmax(0, 1fr));397+ }398+399+ .shikaku-home__feature-strip {400+ grid-template-columns: repeat(3, minmax(0, 1fr));401+ }402+}403+404+.shikaku-play-shell {405+ height: 100dvh;406+ overflow: hidden;407+ background: linear-gradient(180deg, #0f180d 0%, #122411 44%, #0b130b 100%);408+ color: #f7f0d8;409+ font-family:410+ ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",411+ "Courier New", monospace;412+}413+414+.shikaku-play-frame {415+ height: 100%;416+ width: min(100%, 32rem);417+ margin: 0 auto;418+ display: grid;419+ grid-template-rows: auto minmax(0, 1fr);420+ gap: 0.6rem;421+ padding: max(0.75rem, env(safe-area-inset-top))422+ max(0.75rem, env(safe-area-inset-right))423+ max(0.75rem, env(safe-area-inset-bottom))424+ max(0.75rem, env(safe-area-inset-left));425+}426+427+.shikaku-play-header,428+.shikaku-game-status,429+.shikaku-game-board-wrap,430+.shikaku-clue-token {431+ border: 2px solid #0b1209;432+ box-shadow: 4px 4px 0 #0b1209;433+}434+435+.shikaku-play-header {436+ display: grid;437+ gap: 0.25rem;438+ padding: 0.65rem 0.75rem;439+ background: #f4ebcf;440+ color: #11160d;441+}442+443+.shikaku-play-header__row {444+ display: grid;445+ gap: 0.4rem;446+ justify-items: center;447+}448+449+.shikaku-play-day-nav {450+ width: 100%;451+ display: grid;452+ grid-template-columns: 2.4rem 1fr 2.4rem;453+ align-items: center;454+ gap: 0.45rem;455+ text-align: center;456+}457+458+.shikaku-play-day-nav--with-home {459+ grid-template-columns: minmax(3.75rem, auto) 2.4rem 1fr 2.4rem;460+}461+462+.shikaku-play-nav {463+ display: inline-flex;464+ align-items: center;465+ justify-content: center;466+ width: 100%;467+ min-height: 2.35rem;468+ padding: 0.35rem 0.6rem;469+ border: 2px solid #0b1209;470+ background: #d4deb0;471+ color: #11160d;472+ text-decoration: none;473+ font-size: 0.82rem;474+ font-weight: 900;475+ white-space: nowrap;476+ box-shadow: 3px 3px 0 #0b1209;477+}478+479+.shikaku-play-nav--home-text {480+ border: 0;481+ background: transparent;482+ box-shadow: none;483+ text-decoration: underline;484+ text-underline-offset: 0.16em;485+ justify-content: flex-start;486+ padding-inline: 0.2rem 0.35rem;487+}488+489+.shikaku-play-nav--icon {490+ padding: 0;491+ font-size: 1rem;492+ line-height: 1;493+}494+495+.shikaku-play-kicker {496+ font-size: 0.65rem;497+ color: #415338;498+ letter-spacing: 0.08em;499+ text-transform: uppercase;500+}501+502+.shikaku-play-title {503+ font-size: clamp(1.35rem, 4vw, 1.75rem);504+ line-height: 0.95;505+ color: #f8f3de;506+ text-shadow:507+ 1px 0 0 #0b1209,508+ -1px 0 0 #0b1209,509+ 0 1px 0 #0b1209,510+ 0 -1px 0 #0b1209,511+ 3px 3px 0 #3e5f33;512+}513+514+.shikaku-play-hint {515+ font-size: 0.76rem;516+ color: #415338;517+ text-transform: uppercase;518+}519+520+.shikaku-game-shell {521+ min-height: 0;522+ height: 100%;523+ display: grid;524+ grid-template-rows: auto minmax(0, 1fr) auto;525+ gap: 0.5rem;526+ overflow: hidden;527+}528+529+.shikaku-game-status {530+ display: flex;531+ align-items: center;532+ justify-content: space-between;533+ gap: 0.55rem;534+ padding: 0.55rem 0.65rem;535+ background: #efe5c2;536+ color: #11160d;537+}538+539+.shikaku-game-status--solved {540+ background: #d9ebc5;541+}542+543+.shikaku-game-status__meta {544+ display: grid;545+ gap: 0.05rem;546+ min-width: 0;547+}548+549+.shikaku-game-status__meta strong {550+ font-size: 0.9rem;551+ text-transform: uppercase;552+}553+554+.shikaku-game-status__meta span {555+ color: #415338;556+ font-size: 0.73rem;557+ line-height: 1.2;558+ white-space: nowrap;559+ overflow: hidden;560+ text-overflow: ellipsis;561+ text-transform: uppercase;562+}563+564+.shikaku-game-clear {565+ border: 2px solid #0b1209;566+ background: #d4deb0;567+ padding: 0.55rem 0.7rem;568+ font-size: 0.74rem;569+ font-weight: 900;570+ text-transform: uppercase;571+ flex-shrink: 0;572+ box-shadow: 3px 3px 0 #0b1209;573+}574+575+.shikaku-game-board-wrap {576+ min-height: 0;577+ display: grid;578+ place-items: center;579+ padding: 0.25rem;580+ background: #f4ebcf;581+ overflow: hidden;582+}583+584+.shikaku-board--fixed {585+ width: min(100%, calc(100dvh - 21rem));586+ max-width: 100%;587+ aspect-ratio: 1 / 1;588+ display: grid;589+ border: 2px solid #0b1209;590+ background: #fff8e4;591+}592+593+.shikaku-board__cell {594+ width: 100%;595+ aspect-ratio: 1 / 1;596+ border: 1px solid #0b1209;597+ position: relative;598+ font-size: clamp(0.72rem, 2.7vw, 0.96rem);599+ font-weight: 900;600+ color: #11160d;601+}602+603+.shikaku-clue-strip {604+ display: grid;605+ grid-template-columns: repeat(6, minmax(0, 1fr));606+ gap: 0.3rem;607+}608+609+.shikaku-clue-token {610+ display: inline-flex;611+ align-items: center;612+ justify-content: center;613+ gap: 0.22rem;614+ min-height: 2.15rem;615+ padding: 0.2rem 0.1rem;616+ background: #efe5c2;617+ color: #11160d;618+}619+620+.shikaku-clue-token--dim {621+ color: #6f7763;622+}623+624+.shikaku-clue-token__symbol {625+ color: currentColor;626+ font-size: 0.72rem;627+ line-height: 1;628+}629+630+.shikaku-clue-token__value {631+ font-weight: 900;632+ font-size: 0.8rem;633+ line-height: 1;634+}635+636+.shikaku-clue-token.is-placed {637+ background: color-mix(in srgb, var(--token-color) 34%, #efe5c2);638+}639+640+.shikaku-clue-token.is-active {641+ outline: 2px solid #f2cb55;642+ outline-offset: -2px;643+}644+645+@media (max-width: 420px) {646+ .shikaku-play-frame {647+ padding-inline: 0.55rem;648+ }649+650+ .shikaku-board--fixed {651+ width: min(100%, calc(100dvh - 20.4rem));652+ }653+654+ .shikaku-clue-strip {655+ gap: 0.24rem;656+ }657+658+ .shikaku-clue-token {659+ min-height: 2rem;660+ padding: 0.15rem 0.05rem;661+ }662+}663+664+.shikaku-app-shell {665+ min-height: 100dvh;666+ padding: max(1rem, env(safe-area-inset-top))667+ max(1rem, env(safe-area-inset-right))668+ max(1.5rem, env(safe-area-inset-bottom))669+ max(1rem, env(safe-area-inset-left));670+}671+672+.shikaku-board {673+ touch-action: none;674+ user-select: none;675+ -webkit-user-select: none;676+ overscroll-behavior: none;677+}678+679+.shikaku-board button {680+ touch-action: none;681+ -webkit-tap-highlight-color: transparent;682+}683+684+.transition-colors {685+ transition-property: background-color, border-color, color, fill, stroke;686+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);687+ transition-duration: 150ms;688+}689+.my-6 {690+ margin-bottom: 1.5rem;691+ margin-top: 1.5rem;692+}693+.text-4xl {694+ font-size: 2.25rem;695+ line-height: 2.5rem;696+}697+.mx-2 {698+ margin-left: 0.5rem;699+ margin-right: 0.5rem;700+}701+.my-4 {702+ margin-bottom: 1rem;703+ margin-top: 1rem;704+}705+.mx-auto {706+ margin-left: auto;707+ margin-right: auto;708+}709+.px-4 {710+ padding-left: 1rem;711+ padding-right: 1rem;712+}713+.py-8 {714+ padding-bottom: 2rem;715+ padding-top: 2rem;716+}717+.bg-\[\#86efac\] {718+ background-color: #86efac;719+}720+.text-3xl {721+ font-size: 1.875rem;722+ line-height: 2.25rem;723+}724+.py-6 {725+ padding-bottom: 1.5rem;726+ padding-top: 1.5rem;727+}728+.px-2 {729+ padding-left: 0.5rem;730+ padding-right: 0.5rem;731+}732+.py-1 {733+ padding-bottom: 0.25rem;734+ padding-top: 0.25rem;735+}736+.border-gray-500 {737+ border-color: #6b7280;738+}739+.bg-white {740+ background-color: #fff;741+}742+.flex {743+ display: flex;744+}745+.gap-8 {746+ grid-gap: 2rem;747+ gap: 2rem;748+}749+.font-bold {750+ font-weight: 700;751+}752+.max-w-screen-md {753+ max-width: 768px;754+}755+.flex-col {756+ flex-direction: column;757+}758+.items-center {759+ align-items: center;760+}761+.justify-center {762+ justify-content: center;763+}764+.border-2 {765+ border-width: 2px;766+}767+.rounded-sm {768+ border-radius: 0.25rem;769+}770+.hover\:bg-gray-200:hover {771+ background-color: #e5e7eb;772+}773+.tabular-nums {774+ font-variant-numeric: tabular-nums;775+}776+.min-h-screen {777+ min-height: 100vh;778+}779+780+.fresh-gradient {781+ background-color: rgb(134, 239, 172);782+ background-image: linear-gradient(783+ to right bottom,784+ rgb(219, 234, 254),785+ rgb(187, 247, 208),786+ rgb(254, 249, 195)787+ );788+}
A client.ts +2 -0
A components/Button.tsx +17 -0
A data/puzzles/2026-04-16.json +20 -0
A deno.json +63 -0
A deno.lock +1243 -0
@@ -0,0 +1,1243 @@
1+{2+ "version": "5",3+ "specifiers": {4+ "jsr:@deno/esbuild-plugin@^1.2.0": "1.2.1",5+ "jsr:@deno/loader@~0.3.10": "0.3.14",6+ "jsr:@deno/loader@~0.3.2": "0.3.14",7+ "jsr:@fresh/build-id@1": "1.0.1",8+ "jsr:@fresh/core@2": "2.2.2",9+ "jsr:@fresh/core@^2.2.0": "2.2.2",10+ "jsr:@fresh/core@^2.2.2": "2.2.2",11+ "jsr:@fresh/plugin-vite@^1.0.8": "1.0.8",12+ "jsr:@std/assert@*": "1.0.19",13+ "jsr:@std/assert@^1.0.19": "1.0.19",14+ "jsr:@std/bytes@^1.0.6": "1.0.6",15+ "jsr:@std/dotenv@~0.225.5": "0.225.6",16+ "jsr:@std/encoding@^1.0.10": "1.0.10",17+ "jsr:@std/fmt@^1.0.7": "1.0.9",18+ "jsr:@std/fmt@^1.0.8": "1.0.9",19+ "jsr:@std/fs@^1.0.19": "1.0.23",20+ "jsr:@std/html@^1.0.5": "1.0.5",21+ "jsr:@std/http@^1.0.21": "1.0.25",22+ "jsr:@std/internal@^1.0.12": "1.0.12",23+ "jsr:@std/json@^1.0.2": "1.0.3",24+ "jsr:@std/jsonc@^1.0.2": "1.0.2",25+ "jsr:@std/media-types@^1.1.0": "1.1.0",26+ "jsr:@std/path@1": "1.1.4",27+ "jsr:@std/path@^1.1.1": "1.1.4",28+ "jsr:@std/path@^1.1.2": "1.1.4",29+ "jsr:@std/path@^1.1.4": "1.1.4",30+ "jsr:@std/semver@^1.0.6": "1.0.8",31+ "jsr:@std/uuid@^1.0.9": "1.1.0",32+ "npm:@babel/core@^7.28.0": "7.29.0",33+ "npm:@babel/preset-react@^7.27.1": "7.28.5_@babel+core@7.29.0",34+ "npm:@mjackson/node-fetch-server@0.7": "0.7.0",35+ "npm:@opentelemetry/api@^1.9.0": "1.9.1",36+ "npm:@preact/signals@^2.5.0": "2.9.0_preact@10.29.1",37+ "npm:@preact/signals@^2.5.1": "2.9.0_preact@10.29.1",38+ "npm:@prefresh/vite@^2.4.8": "2.4.12_preact@10.29.1_vite@7.3.2__picomatch@4.0.4",39+ "npm:esbuild-wasm@~0.25.11": "0.25.12",40+ "npm:esbuild@0.25.7": "0.25.7",41+ "npm:esbuild@~0.25.5": "0.25.12",42+ "npm:preact-render-to-string@^6.6.3": "6.6.7_preact@10.29.1",43+ "npm:preact@^10.27.2": "10.29.1",44+ "npm:preact@^10.28.2": "10.29.1",45+ "npm:preact@^10.28.3": "10.29.1",46+ "npm:rollup@^4.50.0": "4.60.1",47+ "npm:vite@^7.1.3": "7.3.2_picomatch@4.0.4",48+ "npm:vite@^7.1.4": "7.3.2_picomatch@4.0.4"49+ },50+ "jsr": {51+ "@deno/esbuild-plugin@1.2.1": {52+ "integrity": "df629467913adc1f960149fdfa3a3430ba8c20381c310fba096db244e6c3c9f6",53+ "dependencies": [54+ "jsr:@deno/loader@~0.3.10",55+ "jsr:@std/path@^1.1.1",56+ "npm:esbuild@~0.25.5"57+ ]58+ },59+ "@deno/loader@0.3.14": {60+ "integrity": "97bc63a6cc2d27a60bcdc953f588c5213331d866d44212eebb24cebfb9b011ca"61+ },62+ "@fresh/build-id@1.0.1": {63+ "integrity": "12a2ec25fd52ae9ec68c26848a5696cd1c9b537f7c983c7e56e4fb1e7e816c20",64+ "dependencies": [65+ "jsr:@std/encoding"66+ ]67+ },68+ "@fresh/core@2.2.2": {69+ "integrity": "c34873df58457720f7b915a65fef6fe5cd7215f237cf4d1064d1925b320de96c",70+ "dependencies": [71+ "jsr:@deno/esbuild-plugin",72+ "jsr:@fresh/build-id",73+ "jsr:@std/encoding",74+ "jsr:@std/fmt@^1.0.8",75+ "jsr:@std/fs",76+ "jsr:@std/html",77+ "jsr:@std/http",78+ "jsr:@std/jsonc",79+ "jsr:@std/media-types",80+ "jsr:@std/path@^1.1.2",81+ "jsr:@std/semver",82+ "jsr:@std/uuid",83+ "npm:@opentelemetry/api",84+ "npm:@preact/signals@^2.5.1",85+ "npm:esbuild-wasm",86+ "npm:esbuild@0.25.7",87+ "npm:preact-render-to-string",88+ "npm:preact@^10.28.2",89+ "npm:preact@^10.28.3"90+ ]91+ },92+ "@fresh/plugin-vite@1.0.8": {93+ "integrity": "5780d842ed82e4cbccd93dd8ba2d54bf59dff5aee65921134aab15a4cd457c56",94+ "dependencies": [95+ "jsr:@deno/loader@~0.3.2",96+ "jsr:@fresh/core@2",97+ "jsr:@fresh/core@^2.2.0",98+ "jsr:@std/dotenv",99+ "jsr:@std/fmt@^1.0.7",100+ "jsr:@std/path@1",101+ "npm:@babel/core",102+ "npm:@babel/preset-react",103+ "npm:@mjackson/node-fetch-server",104+ "npm:@prefresh/vite",105+ "npm:rollup",106+ "npm:vite@^7.1.4"107+ ]108+ },109+ "@std/assert@1.0.19": {110+ "integrity": "eaada96ee120cb980bc47e040f82814d786fe8162ecc53c91d8df60b8755991e",111+ "dependencies": [112+ "jsr:@std/internal"113+ ]114+ },115+ "@std/bytes@1.0.6": {116+ "integrity": "f6ac6adbd8ccd99314045f5703e23af0a68d7f7e58364b47d2c7f408aeb5820a"117+ },118+ "@std/dotenv@0.225.6": {119+ "integrity": "1d6f9db72f565bd26790fa034c26e45ecb260b5245417be76c2279e5734c421b"120+ },121+ "@std/encoding@1.0.10": {122+ "integrity": "8783c6384a2d13abd5e9e87a7ae0520a30e9f56aeeaa3bdf910a3eaaf5c811a1"123+ },124+ "@std/fmt@1.0.9": {125+ "integrity": "2487343e8899fb2be5d0e3d35013e54477ada198854e52dd05ed0422eddcabe0"126+ },127+ "@std/fs@1.0.23": {128+ "integrity": "3ecbae4ce4fee03b180fa710caff36bb5adb66631c46a6460aaad49515565a37",129+ "dependencies": [130+ "jsr:@std/path@^1.1.4"131+ ]132+ },133+ "@std/html@1.0.5": {134+ "integrity": "4e2d693f474cae8c16a920fa5e15a3b72267b94b84667f11a50c6dd1cb18d35e"135+ },136+ "@std/http@1.0.25": {137+ "integrity": "577b4252290af1097132812b339fffdd55fb0f4aeb98ff11bdbf67998aa17193",138+ "dependencies": [139+ "jsr:@std/encoding"140+ ]141+ },142+ "@std/internal@1.0.12": {143+ "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027"144+ },145+ "@std/json@1.0.3": {146+ "integrity": "97d5710996293a027b7aa5f0d1f4fa29f246f269e6b5597e08807613f37d426c"147+ },148+ "@std/jsonc@1.0.2": {149+ "integrity": "909605dae3af22bd75b1cbda8d64a32cf1fd2cf6efa3f9e224aba6d22c0f44c7",150+ "dependencies": [151+ "jsr:@std/json"152+ ]153+ },154+ "@std/media-types@1.1.0": {155+ "integrity": "c9d093f0c05c3512932b330e3cc1fe1d627b301db33a4c2c2185c02471d6eaa4"156+ },157+ "@std/path@1.1.4": {158+ "integrity": "1d2d43f39efb1b42f0b1882a25486647cb851481862dc7313390b2bb044314b5",159+ "dependencies": [160+ "jsr:@std/internal"161+ ]162+ },163+ "@std/semver@1.0.8": {164+ "integrity": "dc830e8b8b6a380c895d53fbfd1258dc253704ca57bbe1629ac65fd7830179b7"165+ },166+ "@std/uuid@1.1.0": {167+ "integrity": "6268db2ccf172849c9be80763354ca305d49ef4af41fe995623d44fcc3f7457c",168+ "dependencies": [169+ "jsr:@std/bytes"170+ ]171+ }172+ },173+ "npm": {174+ "@babel/code-frame@7.29.0": {175+ "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",176+ "dependencies": [177+ "@babel/helper-validator-identifier",178+ "js-tokens",179+ "picocolors"180+ ]181+ },182+ "@babel/compat-data@7.29.0": {183+ "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg=="184+ },185+ "@babel/core@7.29.0": {186+ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",187+ "dependencies": [188+ "@babel/code-frame",189+ "@babel/generator",190+ "@babel/helper-compilation-targets",191+ "@babel/helper-module-transforms",192+ "@babel/helpers",193+ "@babel/parser",194+ "@babel/template",195+ "@babel/traverse",196+ "@babel/types",197+ "@jridgewell/remapping",198+ "convert-source-map",199+ "debug",200+ "gensync",201+ "json5",202+ "semver"203+ ]204+ },205+ "@babel/generator@7.29.1": {206+ "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",207+ "dependencies": [208+ "@babel/parser",209+ "@babel/types",210+ "@jridgewell/gen-mapping",211+ "@jridgewell/trace-mapping",212+ "jsesc"213+ ]214+ },215+ "@babel/helper-annotate-as-pure@7.27.3": {216+ "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==",217+ "dependencies": [218+ "@babel/types"219+ ]220+ },221+ "@babel/helper-compilation-targets@7.28.6": {222+ "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",223+ "dependencies": [224+ "@babel/compat-data",225+ "@babel/helper-validator-option",226+ "browserslist",227+ "lru-cache",228+ "semver"229+ ]230+ },231+ "@babel/helper-globals@7.28.0": {232+ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="233+ },234+ "@babel/helper-module-imports@7.28.6": {235+ "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",236+ "dependencies": [237+ "@babel/traverse",238+ "@babel/types"239+ ]240+ },241+ "@babel/helper-module-transforms@7.28.6_@babel+core@7.29.0": {242+ "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",243+ "dependencies": [244+ "@babel/core",245+ "@babel/helper-module-imports",246+ "@babel/helper-validator-identifier",247+ "@babel/traverse"248+ ]249+ },250+ "@babel/helper-plugin-utils@7.28.6": {251+ "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug=="252+ },253+ "@babel/helper-string-parser@7.27.1": {254+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="255+ },256+ "@babel/helper-validator-identifier@7.28.5": {257+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="258+ },259+ "@babel/helper-validator-option@7.27.1": {260+ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="261+ },262+ "@babel/helpers@7.29.2": {263+ "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==",264+ "dependencies": [265+ "@babel/template",266+ "@babel/types"267+ ]268+ },269+ "@babel/parser@7.29.2": {270+ "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==",271+ "dependencies": [272+ "@babel/types"273+ ],274+ "bin": true275+ },276+ "@babel/plugin-syntax-jsx@7.28.6_@babel+core@7.29.0": {277+ "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==",278+ "dependencies": [279+ "@babel/core",280+ "@babel/helper-plugin-utils"281+ ]282+ },283+ "@babel/plugin-transform-react-display-name@7.28.0_@babel+core@7.29.0": {284+ "integrity": "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==",285+ "dependencies": [286+ "@babel/core",287+ "@babel/helper-plugin-utils"288+ ]289+ },290+ "@babel/plugin-transform-react-jsx-development@7.27.1_@babel+core@7.29.0": {291+ "integrity": "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==",292+ "dependencies": [293+ "@babel/core",294+ "@babel/plugin-transform-react-jsx"295+ ]296+ },297+ "@babel/plugin-transform-react-jsx@7.28.6_@babel+core@7.29.0": {298+ "integrity": "sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow==",299+ "dependencies": [300+ "@babel/core",301+ "@babel/helper-annotate-as-pure",302+ "@babel/helper-module-imports",303+ "@babel/helper-plugin-utils",304+ "@babel/plugin-syntax-jsx",305+ "@babel/types"306+ ]307+ },308+ "@babel/plugin-transform-react-pure-annotations@7.27.1_@babel+core@7.29.0": {309+ "integrity": "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==",310+ "dependencies": [311+ "@babel/core",312+ "@babel/helper-annotate-as-pure",313+ "@babel/helper-plugin-utils"314+ ]315+ },316+ "@babel/preset-react@7.28.5_@babel+core@7.29.0": {317+ "integrity": "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==",318+ "dependencies": [319+ "@babel/core",320+ "@babel/helper-plugin-utils",321+ "@babel/helper-validator-option",322+ "@babel/plugin-transform-react-display-name",323+ "@babel/plugin-transform-react-jsx",324+ "@babel/plugin-transform-react-jsx-development",325+ "@babel/plugin-transform-react-pure-annotations"326+ ]327+ },328+ "@babel/template@7.28.6": {329+ "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",330+ "dependencies": [331+ "@babel/code-frame",332+ "@babel/parser",333+ "@babel/types"334+ ]335+ },336+ "@babel/traverse@7.29.0": {337+ "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",338+ "dependencies": [339+ "@babel/code-frame",340+ "@babel/generator",341+ "@babel/helper-globals",342+ "@babel/parser",343+ "@babel/template",344+ "@babel/types",345+ "debug"346+ ]347+ },348+ "@babel/types@7.29.0": {349+ "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",350+ "dependencies": [351+ "@babel/helper-string-parser",352+ "@babel/helper-validator-identifier"353+ ]354+ },355+ "@esbuild/aix-ppc64@0.25.12": {356+ "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",357+ "os": ["aix"],358+ "cpu": ["ppc64"]359+ },360+ "@esbuild/aix-ppc64@0.25.7": {361+ "integrity": "sha512-uD0kKFHh6ETr8TqEtaAcV+dn/2qnYbH/+8wGEdY70Qf7l1l/jmBUbrmQqwiPKAQE6cOQ7dTj6Xr0HzQDGHyceQ==",362+ "os": ["aix"],363+ "cpu": ["ppc64"]364+ },365+ "@esbuild/aix-ppc64@0.27.7": {366+ "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==",367+ "os": ["aix"],368+ "cpu": ["ppc64"]369+ },370+ "@esbuild/android-arm64@0.25.12": {371+ "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",372+ "os": ["android"],373+ "cpu": ["arm64"]374+ },375+ "@esbuild/android-arm64@0.25.7": {376+ "integrity": "sha512-p0ohDnwyIbAtztHTNUTzN5EGD/HJLs1bwysrOPgSdlIA6NDnReoVfoCyxG6W1d85jr2X80Uq5KHftyYgaK9LPQ==",377+ "os": ["android"],378+ "cpu": ["arm64"]379+ },380+ "@esbuild/android-arm64@0.27.7": {381+ "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==",382+ "os": ["android"],383+ "cpu": ["arm64"]384+ },385+ "@esbuild/android-arm@0.25.12": {386+ "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",387+ "os": ["android"],388+ "cpu": ["arm"]389+ },390+ "@esbuild/android-arm@0.25.7": {391+ "integrity": "sha512-Jhuet0g1k9rAJHrXGIh7sFknFuT4sfytYZpZpuZl7YKDhnPByVAm5oy2LEBmMbuYf3ejWVYCc2seX81Mk+madA==",392+ "os": ["android"],393+ "cpu": ["arm"]394+ },395+ "@esbuild/android-arm@0.27.7": {396+ "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==",397+ "os": ["android"],398+ "cpu": ["arm"]399+ },400+ "@esbuild/android-x64@0.25.12": {401+ "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",402+ "os": ["android"],403+ "cpu": ["x64"]404+ },405+ "@esbuild/android-x64@0.25.7": {406+ "integrity": "sha512-mMxIJFlSgVK23HSsII3ZX9T2xKrBCDGyk0qiZnIW10LLFFtZLkFD6imZHu7gUo2wkNZwS9Yj3mOtZD3ZPcjCcw==",407+ "os": ["android"],408+ "cpu": ["x64"]409+ },410+ "@esbuild/android-x64@0.27.7": {411+ "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==",412+ "os": ["android"],413+ "cpu": ["x64"]414+ },415+ "@esbuild/darwin-arm64@0.25.12": {416+ "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",417+ "os": ["darwin"],418+ "cpu": ["arm64"]419+ },420+ "@esbuild/darwin-arm64@0.25.7": {421+ "integrity": "sha512-jyOFLGP2WwRwxM8F1VpP6gcdIJc8jq2CUrURbbTouJoRO7XCkU8GdnTDFIHdcifVBT45cJlOYsZ1kSlfbKjYUQ==",422+ "os": ["darwin"],423+ "cpu": ["arm64"]424+ },425+ "@esbuild/darwin-arm64@0.27.7": {426+ "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==",427+ "os": ["darwin"],428+ "cpu": ["arm64"]429+ },430+ "@esbuild/darwin-x64@0.25.12": {431+ "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",432+ "os": ["darwin"],433+ "cpu": ["x64"]434+ },435+ "@esbuild/darwin-x64@0.25.7": {436+ "integrity": "sha512-m9bVWqZCwQ1BthruifvG64hG03zzz9gE2r/vYAhztBna1/+qXiHyP9WgnyZqHgGeXoimJPhAmxfbeU+nMng6ZA==",437+ "os": ["darwin"],438+ "cpu": ["x64"]439+ },440+ "@esbuild/darwin-x64@0.27.7": {441+ "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==",442+ "os": ["darwin"],443+ "cpu": ["x64"]444+ },445+ "@esbuild/freebsd-arm64@0.25.12": {446+ "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",447+ "os": ["freebsd"],448+ "cpu": ["arm64"]449+ },450+ "@esbuild/freebsd-arm64@0.25.7": {451+ "integrity": "sha512-Bss7P4r6uhr3kDzRjPNEnTm/oIBdTPRNQuwaEFWT/uvt6A1YzK/yn5kcx5ZxZ9swOga7LqeYlu7bDIpDoS01bA==",452+ "os": ["freebsd"],453+ "cpu": ["arm64"]454+ },455+ "@esbuild/freebsd-arm64@0.27.7": {456+ "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==",457+ "os": ["freebsd"],458+ "cpu": ["arm64"]459+ },460+ "@esbuild/freebsd-x64@0.25.12": {461+ "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",462+ "os": ["freebsd"],463+ "cpu": ["x64"]464+ },465+ "@esbuild/freebsd-x64@0.25.7": {466+ "integrity": "sha512-S3BFyjW81LXG7Vqmr37ddbThrm3A84yE7ey/ERBlK9dIiaWgrjRlre3pbG7txh1Uaxz8N7wGGQXmC9zV+LIpBQ==",467+ "os": ["freebsd"],468+ "cpu": ["x64"]469+ },470+ "@esbuild/freebsd-x64@0.27.7": {471+ "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==",472+ "os": ["freebsd"],473+ "cpu": ["x64"]474+ },475+ "@esbuild/linux-arm64@0.25.12": {476+ "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",477+ "os": ["linux"],478+ "cpu": ["arm64"]479+ },480+ "@esbuild/linux-arm64@0.25.7": {481+ "integrity": "sha512-HfQZQqrNOfS1Okn7PcsGUqHymL1cWGBslf78dGvtrj8q7cN3FkapFgNA4l/a5lXDwr7BqP2BSO6mz9UremNPbg==",482+ "os": ["linux"],483+ "cpu": ["arm64"]484+ },485+ "@esbuild/linux-arm64@0.27.7": {486+ "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==",487+ "os": ["linux"],488+ "cpu": ["arm64"]489+ },490+ "@esbuild/linux-arm@0.25.12": {491+ "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",492+ "os": ["linux"],493+ "cpu": ["arm"]494+ },495+ "@esbuild/linux-arm@0.25.7": {496+ "integrity": "sha512-JZMIci/1m5vfQuhKoFXogCKVYVfYQmoZJg8vSIMR4TUXbF+0aNlfXH3DGFEFMElT8hOTUF5hisdZhnrZO/bkDw==",497+ "os": ["linux"],498+ "cpu": ["arm"]499+ },500+ "@esbuild/linux-arm@0.27.7": {501+ "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==",502+ "os": ["linux"],503+ "cpu": ["arm"]504+ },505+ "@esbuild/linux-ia32@0.25.12": {506+ "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",507+ "os": ["linux"],508+ "cpu": ["ia32"]509+ },510+ "@esbuild/linux-ia32@0.25.7": {511+ "integrity": "sha512-9Jex4uVpdeofiDxnwHRgen+j6398JlX4/6SCbbEFEXN7oMO2p0ueLN+e+9DdsdPLUdqns607HmzEFnxwr7+5wQ==",512+ "os": ["linux"],513+ "cpu": ["ia32"]514+ },515+ "@esbuild/linux-ia32@0.27.7": {516+ "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==",517+ "os": ["linux"],518+ "cpu": ["ia32"]519+ },520+ "@esbuild/linux-loong64@0.25.12": {521+ "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",522+ "os": ["linux"],523+ "cpu": ["loong64"]524+ },525+ "@esbuild/linux-loong64@0.25.7": {526+ "integrity": "sha512-TG1KJqjBlN9IHQjKVUYDB0/mUGgokfhhatlay8aZ/MSORMubEvj/J1CL8YGY4EBcln4z7rKFbsH+HeAv0d471w==",527+ "os": ["linux"],528+ "cpu": ["loong64"]529+ },530+ "@esbuild/linux-loong64@0.27.7": {531+ "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==",532+ "os": ["linux"],533+ "cpu": ["loong64"]534+ },535+ "@esbuild/linux-mips64el@0.25.12": {536+ "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",537+ "os": ["linux"],538+ "cpu": ["mips64el"]539+ },540+ "@esbuild/linux-mips64el@0.25.7": {541+ "integrity": "sha512-Ty9Hj/lx7ikTnhOfaP7ipEm/ICcBv94i/6/WDg0OZ3BPBHhChsUbQancoWYSO0WNkEiSW5Do4febTTy4x1qYQQ==",542+ "os": ["linux"],543+ "cpu": ["mips64el"]544+ },545+ "@esbuild/linux-mips64el@0.27.7": {546+ "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==",547+ "os": ["linux"],548+ "cpu": ["mips64el"]549+ },550+ "@esbuild/linux-ppc64@0.25.12": {551+ "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",552+ "os": ["linux"],553+ "cpu": ["ppc64"]554+ },555+ "@esbuild/linux-ppc64@0.25.7": {556+ "integrity": "sha512-MrOjirGQWGReJl3BNQ58BLhUBPpWABnKrnq8Q/vZWWwAB1wuLXOIxS2JQ1LT3+5T+3jfPh0tyf5CpbyQHqnWIQ==",557+ "os": ["linux"],558+ "cpu": ["ppc64"]559+ },560+ "@esbuild/linux-ppc64@0.27.7": {561+ "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==",562+ "os": ["linux"],563+ "cpu": ["ppc64"]564+ },565+ "@esbuild/linux-riscv64@0.25.12": {566+ "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",567+ "os": ["linux"],568+ "cpu": ["riscv64"]569+ },570+ "@esbuild/linux-riscv64@0.25.7": {571+ "integrity": "sha512-9pr23/pqzyqIZEZmQXnFyqp3vpa+KBk5TotfkzGMqpw089PGm0AIowkUppHB9derQzqniGn3wVXgck19+oqiOw==",572+ "os": ["linux"],573+ "cpu": ["riscv64"]574+ },575+ "@esbuild/linux-riscv64@0.27.7": {576+ "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==",577+ "os": ["linux"],578+ "cpu": ["riscv64"]579+ },580+ "@esbuild/linux-s390x@0.25.12": {581+ "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",582+ "os": ["linux"],583+ "cpu": ["s390x"]584+ },585+ "@esbuild/linux-s390x@0.25.7": {586+ "integrity": "sha512-4dP11UVGh9O6Y47m8YvW8eoA3r8qL2toVZUbBKyGta8j6zdw1cn9F/Rt59/Mhv0OgY68pHIMjGXWOUaykCnx+w==",587+ "os": ["linux"],588+ "cpu": ["s390x"]589+ },590+ "@esbuild/linux-s390x@0.27.7": {591+ "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==",592+ "os": ["linux"],593+ "cpu": ["s390x"]594+ },595+ "@esbuild/linux-x64@0.25.12": {596+ "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==",597+ "os": ["linux"],598+ "cpu": ["x64"]599+ },600+ "@esbuild/linux-x64@0.25.7": {601+ "integrity": "sha512-ghJMAJTdw/0uhz7e7YnpdX1xVn7VqA0GrWrAO2qKMuqbvgHT2VZiBv1BQ//VcHsPir4wsL3P2oPggfKPzTKoCA==",602+ "os": ["linux"],603+ "cpu": ["x64"]604+ },605+ "@esbuild/linux-x64@0.27.7": {606+ "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==",607+ "os": ["linux"],608+ "cpu": ["x64"]609+ },610+ "@esbuild/netbsd-arm64@0.25.12": {611+ "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",612+ "os": ["netbsd"],613+ "cpu": ["arm64"]614+ },615+ "@esbuild/netbsd-arm64@0.25.7": {616+ "integrity": "sha512-bwXGEU4ua45+u5Ci/a55B85KWaDSRS8NPOHtxy2e3etDjbz23wlry37Ffzapz69JAGGc4089TBo+dGzydQmydg==",617+ "os": ["netbsd"],618+ "cpu": ["arm64"]619+ },620+ "@esbuild/netbsd-arm64@0.27.7": {621+ "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==",622+ "os": ["netbsd"],623+ "cpu": ["arm64"]624+ },625+ "@esbuild/netbsd-x64@0.25.12": {626+ "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",627+ "os": ["netbsd"],628+ "cpu": ["x64"]629+ },630+ "@esbuild/netbsd-x64@0.25.7": {631+ "integrity": "sha512-tUZRvLtgLE5OyN46sPSYlgmHoBS5bx2URSrgZdW1L1teWPYVmXh+QN/sKDqkzBo/IHGcKcHLKDhBeVVkO7teEA==",632+ "os": ["netbsd"],633+ "cpu": ["x64"]634+ },635+ "@esbuild/netbsd-x64@0.27.7": {636+ "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==",637+ "os": ["netbsd"],638+ "cpu": ["x64"]639+ },640+ "@esbuild/openbsd-arm64@0.25.12": {641+ "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",642+ "os": ["openbsd"],643+ "cpu": ["arm64"]644+ },645+ "@esbuild/openbsd-arm64@0.25.7": {646+ "integrity": "sha512-bTJ50aoC+WDlDGBReWYiObpYvQfMjBNlKztqoNUL0iUkYtwLkBQQeEsTq/I1KyjsKA5tyov6VZaPb8UdD6ci6Q==",647+ "os": ["openbsd"],648+ "cpu": ["arm64"]649+ },650+ "@esbuild/openbsd-arm64@0.27.7": {651+ "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==",652+ "os": ["openbsd"],653+ "cpu": ["arm64"]654+ },655+ "@esbuild/openbsd-x64@0.25.12": {656+ "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",657+ "os": ["openbsd"],658+ "cpu": ["x64"]659+ },660+ "@esbuild/openbsd-x64@0.25.7": {661+ "integrity": "sha512-TA9XfJrgzAipFUU895jd9j2SyDh9bbNkK2I0gHcvqb/o84UeQkBpi/XmYX3cO1q/9hZokdcDqQxIi6uLVrikxg==",662+ "os": ["openbsd"],663+ "cpu": ["x64"]664+ },665+ "@esbuild/openbsd-x64@0.27.7": {666+ "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==",667+ "os": ["openbsd"],668+ "cpu": ["x64"]669+ },670+ "@esbuild/openharmony-arm64@0.25.12": {671+ "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",672+ "os": ["openharmony"],673+ "cpu": ["arm64"]674+ },675+ "@esbuild/openharmony-arm64@0.25.7": {676+ "integrity": "sha512-5VTtExUrWwHHEUZ/N+rPlHDwVFQ5aME7vRJES8+iQ0xC/bMYckfJ0l2n3yGIfRoXcK/wq4oXSItZAz5wslTKGw==",677+ "os": ["openharmony"],678+ "cpu": ["arm64"]679+ },680+ "@esbuild/openharmony-arm64@0.27.7": {681+ "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==",682+ "os": ["openharmony"],683+ "cpu": ["arm64"]684+ },685+ "@esbuild/sunos-x64@0.25.12": {686+ "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",687+ "os": ["sunos"],688+ "cpu": ["x64"]689+ },690+ "@esbuild/sunos-x64@0.25.7": {691+ "integrity": "sha512-umkbn7KTxsexhv2vuuJmj9kggd4AEtL32KodkJgfhNOHMPtQ55RexsaSrMb+0+jp9XL4I4o2y91PZauVN4cH3A==",692+ "os": ["sunos"],693+ "cpu": ["x64"]694+ },695+ "@esbuild/sunos-x64@0.27.7": {696+ "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==",697+ "os": ["sunos"],698+ "cpu": ["x64"]699+ },700+ "@esbuild/win32-arm64@0.25.12": {701+ "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",702+ "os": ["win32"],703+ "cpu": ["arm64"]704+ },705+ "@esbuild/win32-arm64@0.25.7": {706+ "integrity": "sha512-j20JQGP/gz8QDgzl5No5Gr4F6hurAZvtkFxAKhiv2X49yi/ih8ECK4Y35YnjlMogSKJk931iNMcd35BtZ4ghfw==",707+ "os": ["win32"],708+ "cpu": ["arm64"]709+ },710+ "@esbuild/win32-arm64@0.27.7": {711+ "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==",712+ "os": ["win32"],713+ "cpu": ["arm64"]714+ },715+ "@esbuild/win32-ia32@0.25.12": {716+ "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",717+ "os": ["win32"],718+ "cpu": ["ia32"]719+ },720+ "@esbuild/win32-ia32@0.25.7": {721+ "integrity": "sha512-4qZ6NUfoiiKZfLAXRsvFkA0hoWVM+1y2bSHXHkpdLAs/+r0LgwqYohmfZCi985c6JWHhiXP30mgZawn/XrqAkQ==",722+ "os": ["win32"],723+ "cpu": ["ia32"]724+ },725+ "@esbuild/win32-ia32@0.27.7": {726+ "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==",727+ "os": ["win32"],728+ "cpu": ["ia32"]729+ },730+ "@esbuild/win32-x64@0.25.12": {731+ "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",732+ "os": ["win32"],733+ "cpu": ["x64"]734+ },735+ "@esbuild/win32-x64@0.25.7": {736+ "integrity": "sha512-FaPsAHTwm+1Gfvn37Eg3E5HIpfR3i6x1AIcla/MkqAIupD4BW3MrSeUqfoTzwwJhk3WE2/KqUn4/eenEJC76VA==",737+ "os": ["win32"],738+ "cpu": ["x64"]739+ },740+ "@esbuild/win32-x64@0.27.7": {741+ "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==",742+ "os": ["win32"],743+ "cpu": ["x64"]744+ },745+ "@jridgewell/gen-mapping@0.3.13": {746+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",747+ "dependencies": [748+ "@jridgewell/sourcemap-codec",749+ "@jridgewell/trace-mapping"750+ ]751+ },752+ "@jridgewell/remapping@2.3.5": {753+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",754+ "dependencies": [755+ "@jridgewell/gen-mapping",756+ "@jridgewell/trace-mapping"757+ ]758+ },759+ "@jridgewell/resolve-uri@3.1.2": {760+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="761+ },762+ "@jridgewell/sourcemap-codec@1.5.5": {763+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="764+ },765+ "@jridgewell/trace-mapping@0.3.31": {766+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",767+ "dependencies": [768+ "@jridgewell/resolve-uri",769+ "@jridgewell/sourcemap-codec"770+ ]771+ },772+ "@mjackson/node-fetch-server@0.7.0": {773+ "integrity": "sha512-un8diyEBKU3BTVj3GzlTPA1kIjCkGdD+AMYQy31Gf9JCkfoZzwgJ79GUtHrF2BN3XPNMLpubbzPcxys+a3uZEw=="774+ },775+ "@opentelemetry/api@1.9.1": {776+ "integrity": "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q=="777+ },778+ "@preact/signals-core@1.14.1": {779+ "integrity": "sha512-vxPpfXqrwUe9lpjqfYNjAF/0RF/eFGeLgdJzdmIIZjpOnTmGmAB4BjWone562mJGMRP4frU6iZ6ei3PDsu52Ng=="780+ },781+ "@preact/signals@2.9.0_preact@10.29.1": {782+ "integrity": "sha512-hYrY0KyUqkDgOl1qba/JGn6y81pXnurn21PMaxfcMwdncdZ3M/oVdmpTvEnsGjh48dIwDVc7bjWHqIsngSjYug==",783+ "dependencies": [784+ "@preact/signals-core",785+ "preact"786+ ]787+ },788+ "@prefresh/babel-plugin@0.5.3": {789+ "integrity": "sha512-57LX2SHs4BX2s1IwCjNzTE2OJeEepRCNf1VTEpbNcUyHfMO68eeOWGDIt4ob9aYlW6PEWZ1SuwNikuoIXANDtQ=="790+ },791+ "@prefresh/core@1.5.9_preact@10.29.1": {792+ "integrity": "sha512-IKBKCPaz34OFVC+adiQ2qaTF5qdztO2/4ZPf4KsRTgjKosWqxVXmEbxCiUydYZRY8GVie+DQlKzQr9gt6HQ+EQ==",793+ "dependencies": [794+ "preact"795+ ]796+ },797+ "@prefresh/utils@1.2.1": {798+ "integrity": "sha512-vq/sIuN5nYfYzvyayXI4C2QkprfNaHUQ9ZX+3xLD8nL3rWyzpxOm1+K7RtMbhd+66QcaISViK7amjnheQ/4WZw=="799+ },800+ "@prefresh/vite@2.4.12_preact@10.29.1_vite@7.3.2__picomatch@4.0.4": {801+ "integrity": "sha512-FY1fzXpUjiuosznMV0YM7XAOPZjB5FIdWS0W24+XnlxYkt9hNAwwsiKYn+cuTEoMtD/ZVazS5QVssBr9YhpCQA==",802+ "dependencies": [803+ "@babel/core",804+ "@prefresh/babel-plugin",805+ "@prefresh/core",806+ "@prefresh/utils",807+ "@rollup/pluginutils",808+ "preact",809+ "vite"810+ ]811+ },812+ "@rollup/pluginutils@4.2.1": {813+ "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==",814+ "dependencies": [815+ "estree-walker",816+ "picomatch@2.3.2"817+ ]818+ },819+ "@rollup/rollup-android-arm-eabi@4.60.1": {820+ "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==",821+ "os": ["android"],822+ "cpu": ["arm"]823+ },824+ "@rollup/rollup-android-arm64@4.60.1": {825+ "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==",826+ "os": ["android"],827+ "cpu": ["arm64"]828+ },829+ "@rollup/rollup-darwin-arm64@4.60.1": {830+ "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==",831+ "os": ["darwin"],832+ "cpu": ["arm64"]833+ },834+ "@rollup/rollup-darwin-x64@4.60.1": {835+ "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==",836+ "os": ["darwin"],837+ "cpu": ["x64"]838+ },839+ "@rollup/rollup-freebsd-arm64@4.60.1": {840+ "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==",841+ "os": ["freebsd"],842+ "cpu": ["arm64"]843+ },844+ "@rollup/rollup-freebsd-x64@4.60.1": {845+ "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==",846+ "os": ["freebsd"],847+ "cpu": ["x64"]848+ },849+ "@rollup/rollup-linux-arm-gnueabihf@4.60.1": {850+ "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==",851+ "os": ["linux"],852+ "cpu": ["arm"]853+ },854+ "@rollup/rollup-linux-arm-musleabihf@4.60.1": {855+ "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==",856+ "os": ["linux"],857+ "cpu": ["arm"]858+ },859+ "@rollup/rollup-linux-arm64-gnu@4.60.1": {860+ "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==",861+ "os": ["linux"],862+ "cpu": ["arm64"]863+ },864+ "@rollup/rollup-linux-arm64-musl@4.60.1": {865+ "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==",866+ "os": ["linux"],867+ "cpu": ["arm64"]868+ },869+ "@rollup/rollup-linux-loong64-gnu@4.60.1": {870+ "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==",871+ "os": ["linux"],872+ "cpu": ["loong64"]873+ },874+ "@rollup/rollup-linux-loong64-musl@4.60.1": {875+ "integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==",876+ "os": ["linux"],877+ "cpu": ["loong64"]878+ },879+ "@rollup/rollup-linux-ppc64-gnu@4.60.1": {880+ "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==",881+ "os": ["linux"],882+ "cpu": ["ppc64"]883+ },884+ "@rollup/rollup-linux-ppc64-musl@4.60.1": {885+ "integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==",886+ "os": ["linux"],887+ "cpu": ["ppc64"]888+ },889+ "@rollup/rollup-linux-riscv64-gnu@4.60.1": {890+ "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==",891+ "os": ["linux"],892+ "cpu": ["riscv64"]893+ },894+ "@rollup/rollup-linux-riscv64-musl@4.60.1": {895+ "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==",896+ "os": ["linux"],897+ "cpu": ["riscv64"]898+ },899+ "@rollup/rollup-linux-s390x-gnu@4.60.1": {900+ "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==",901+ "os": ["linux"],902+ "cpu": ["s390x"]903+ },904+ "@rollup/rollup-linux-x64-gnu@4.60.1": {905+ "integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==",906+ "os": ["linux"],907+ "cpu": ["x64"]908+ },909+ "@rollup/rollup-linux-x64-musl@4.60.1": {910+ "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==",911+ "os": ["linux"],912+ "cpu": ["x64"]913+ },914+ "@rollup/rollup-openbsd-x64@4.60.1": {915+ "integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==",916+ "os": ["openbsd"],917+ "cpu": ["x64"]918+ },919+ "@rollup/rollup-openharmony-arm64@4.60.1": {920+ "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==",921+ "os": ["openharmony"],922+ "cpu": ["arm64"]923+ },924+ "@rollup/rollup-win32-arm64-msvc@4.60.1": {925+ "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==",926+ "os": ["win32"],927+ "cpu": ["arm64"]928+ },929+ "@rollup/rollup-win32-ia32-msvc@4.60.1": {930+ "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==",931+ "os": ["win32"],932+ "cpu": ["ia32"]933+ },934+ "@rollup/rollup-win32-x64-gnu@4.60.1": {935+ "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==",936+ "os": ["win32"],937+ "cpu": ["x64"]938+ },939+ "@rollup/rollup-win32-x64-msvc@4.60.1": {940+ "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==",941+ "os": ["win32"],942+ "cpu": ["x64"]943+ },944+ "@types/estree@1.0.8": {945+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="946+ },947+ "baseline-browser-mapping@2.10.19": {948+ "integrity": "sha512-qCkNLi2sfBOn8XhZQ0FXsT1Ki/Yo5P90hrkRamVFRS7/KV9hpfA4HkoWNU152+8w0zPjnxo5psx5NL3PSGgv5g==",949+ "bin": true950+ },951+ "browserslist@4.28.2": {952+ "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==",953+ "dependencies": [954+ "baseline-browser-mapping",955+ "caniuse-lite",956+ "electron-to-chromium",957+ "node-releases",958+ "update-browserslist-db"959+ ],960+ "bin": true961+ },962+ "caniuse-lite@1.0.30001788": {963+ "integrity": "sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ=="964+ },965+ "convert-source-map@2.0.0": {966+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="967+ },968+ "debug@4.4.3": {969+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",970+ "dependencies": [971+ "ms"972+ ]973+ },974+ "electron-to-chromium@1.5.339": {975+ "integrity": "sha512-Is+0BBHJ4NrdpAYiperrmp53pLywG/yV/6lIMTAnhxvzj/Cmn5Q/ogSHC6AKe7X+8kPLxxFk0cs5oc/3j/fxIg=="976+ },977+ "esbuild-wasm@0.25.12": {978+ "integrity": "sha512-rZqkjL3Y6FwLpSHzLnaEy8Ps6veCNo1kZa9EOfJvmWtBq5dJH4iVjfmOO6Mlkv9B0tt9WFPFmb/VxlgJOnueNg==",979+ "bin": true980+ },981+ "esbuild@0.25.12": {982+ "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",983+ "optionalDependencies": [984+ "@esbuild/aix-ppc64@0.25.12",985+ "@esbuild/android-arm@0.25.12",986+ "@esbuild/android-arm64@0.25.12",987+ "@esbuild/android-x64@0.25.12",988+ "@esbuild/darwin-arm64@0.25.12",989+ "@esbuild/darwin-x64@0.25.12",990+ "@esbuild/freebsd-arm64@0.25.12",991+ "@esbuild/freebsd-x64@0.25.12",992+ "@esbuild/linux-arm@0.25.12",993+ "@esbuild/linux-arm64@0.25.12",994+ "@esbuild/linux-ia32@0.25.12",995+ "@esbuild/linux-loong64@0.25.12",996+ "@esbuild/linux-mips64el@0.25.12",997+ "@esbuild/linux-ppc64@0.25.12",998+ "@esbuild/linux-riscv64@0.25.12",999+ "@esbuild/linux-s390x@0.25.12",1000+ "@esbuild/linux-x64@0.25.12",1001+ "@esbuild/netbsd-arm64@0.25.12",1002+ "@esbuild/netbsd-x64@0.25.12",1003+ "@esbuild/openbsd-arm64@0.25.12",1004+ "@esbuild/openbsd-x64@0.25.12",1005+ "@esbuild/openharmony-arm64@0.25.12",1006+ "@esbuild/sunos-x64@0.25.12",1007+ "@esbuild/win32-arm64@0.25.12",1008+ "@esbuild/win32-ia32@0.25.12",1009+ "@esbuild/win32-x64@0.25.12"1010+ ],1011+ "scripts": true,1012+ "bin": true1013+ },1014+ "esbuild@0.25.7": {1015+ "integrity": "sha512-daJB0q2dmTzo90L9NjRaohhRWrCzYxWNFTjEi72/h+p5DcY3yn4MacWfDakHmaBaDzDiuLJsCh0+6LK/iX+c+Q==",1016+ "optionalDependencies": [1017+ "@esbuild/aix-ppc64@0.25.7",1018+ "@esbuild/android-arm@0.25.7",1019+ "@esbuild/android-arm64@0.25.7",1020+ "@esbuild/android-x64@0.25.7",1021+ "@esbuild/darwin-arm64@0.25.7",1022+ "@esbuild/darwin-x64@0.25.7",1023+ "@esbuild/freebsd-arm64@0.25.7",1024+ "@esbuild/freebsd-x64@0.25.7",1025+ "@esbuild/linux-arm@0.25.7",1026+ "@esbuild/linux-arm64@0.25.7",1027+ "@esbuild/linux-ia32@0.25.7",1028+ "@esbuild/linux-loong64@0.25.7",1029+ "@esbuild/linux-mips64el@0.25.7",1030+ "@esbuild/linux-ppc64@0.25.7",1031+ "@esbuild/linux-riscv64@0.25.7",1032+ "@esbuild/linux-s390x@0.25.7",1033+ "@esbuild/linux-x64@0.25.7",1034+ "@esbuild/netbsd-arm64@0.25.7",1035+ "@esbuild/netbsd-x64@0.25.7",1036+ "@esbuild/openbsd-arm64@0.25.7",1037+ "@esbuild/openbsd-x64@0.25.7",1038+ "@esbuild/openharmony-arm64@0.25.7",1039+ "@esbuild/sunos-x64@0.25.7",1040+ "@esbuild/win32-arm64@0.25.7",1041+ "@esbuild/win32-ia32@0.25.7",1042+ "@esbuild/win32-x64@0.25.7"1043+ ],1044+ "scripts": true,1045+ "bin": true1046+ },1047+ "esbuild@0.27.7": {1048+ "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==",1049+ "optionalDependencies": [1050+ "@esbuild/aix-ppc64@0.27.7",1051+ "@esbuild/android-arm@0.27.7",1052+ "@esbuild/android-arm64@0.27.7",1053+ "@esbuild/android-x64@0.27.7",1054+ "@esbuild/darwin-arm64@0.27.7",1055+ "@esbuild/darwin-x64@0.27.7",1056+ "@esbuild/freebsd-arm64@0.27.7",1057+ "@esbuild/freebsd-x64@0.27.7",1058+ "@esbuild/linux-arm@0.27.7",1059+ "@esbuild/linux-arm64@0.27.7",1060+ "@esbuild/linux-ia32@0.27.7",1061+ "@esbuild/linux-loong64@0.27.7",1062+ "@esbuild/linux-mips64el@0.27.7",1063+ "@esbuild/linux-ppc64@0.27.7",1064+ "@esbuild/linux-riscv64@0.27.7",1065+ "@esbuild/linux-s390x@0.27.7",1066+ "@esbuild/linux-x64@0.27.7",1067+ "@esbuild/netbsd-arm64@0.27.7",1068+ "@esbuild/netbsd-x64@0.27.7",1069+ "@esbuild/openbsd-arm64@0.27.7",1070+ "@esbuild/openbsd-x64@0.27.7",1071+ "@esbuild/openharmony-arm64@0.27.7",1072+ "@esbuild/sunos-x64@0.27.7",1073+ "@esbuild/win32-arm64@0.27.7",1074+ "@esbuild/win32-ia32@0.27.7",1075+ "@esbuild/win32-x64@0.27.7"1076+ ],1077+ "scripts": true,1078+ "bin": true1079+ },1080+ "escalade@3.2.0": {1081+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="1082+ },1083+ "estree-walker@2.0.2": {1084+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="1085+ },1086+ "fdir@6.5.0_picomatch@4.0.4": {1087+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",1088+ "dependencies": [1089+ "picomatch@4.0.4"1090+ ],1091+ "optionalPeers": [1092+ "picomatch@4.0.4"1093+ ]1094+ },1095+ "fsevents@2.3.3": {1096+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",1097+ "os": ["darwin"],1098+ "scripts": true1099+ },1100+ "gensync@1.0.0-beta.2": {1101+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="1102+ },1103+ "js-tokens@4.0.0": {1104+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="1105+ },1106+ "jsesc@3.1.0": {1107+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",1108+ "bin": true1109+ },1110+ "json5@2.2.3": {1111+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",1112+ "bin": true1113+ },1114+ "lru-cache@5.1.1": {1115+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",1116+ "dependencies": [1117+ "yallist"1118+ ]1119+ },1120+ "ms@2.1.3": {1121+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="1122+ },1123+ "nanoid@3.3.11": {1124+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",1125+ "bin": true1126+ },1127+ "node-releases@2.0.37": {1128+ "integrity": "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg=="1129+ },1130+ "picocolors@1.1.1": {1131+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="1132+ },1133+ "picomatch@2.3.2": {1134+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="1135+ },1136+ "picomatch@4.0.4": {1137+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="1138+ },1139+ "postcss@8.5.10": {1140+ "integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==",1141+ "dependencies": [1142+ "nanoid",1143+ "picocolors",1144+ "source-map-js"1145+ ]1146+ },1147+ "preact-render-to-string@6.6.7_preact@10.29.1": {1148+ "integrity": "sha512-3XdbsX3+vn9dQW+jJI/FsI9rlkgl6dbeUpqLsChak6jp3j3auFqBCkno7VChbMFs5Q8ylBj6DrUkKRwtVN3nvw==",1149+ "dependencies": [1150+ "preact"1151+ ]1152+ },1153+ "preact@10.29.1": {1154+ "integrity": "sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg=="1155+ },1156+ "rollup@4.60.1": {1157+ "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==",1158+ "dependencies": [1159+ "@types/estree"1160+ ],1161+ "optionalDependencies": [1162+ "@rollup/rollup-android-arm-eabi",1163+ "@rollup/rollup-android-arm64",1164+ "@rollup/rollup-darwin-arm64",1165+ "@rollup/rollup-darwin-x64",1166+ "@rollup/rollup-freebsd-arm64",1167+ "@rollup/rollup-freebsd-x64",1168+ "@rollup/rollup-linux-arm-gnueabihf",1169+ "@rollup/rollup-linux-arm-musleabihf",1170+ "@rollup/rollup-linux-arm64-gnu",1171+ "@rollup/rollup-linux-arm64-musl",1172+ "@rollup/rollup-linux-loong64-gnu",1173+ "@rollup/rollup-linux-loong64-musl",1174+ "@rollup/rollup-linux-ppc64-gnu",1175+ "@rollup/rollup-linux-ppc64-musl",1176+ "@rollup/rollup-linux-riscv64-gnu",1177+ "@rollup/rollup-linux-riscv64-musl",1178+ "@rollup/rollup-linux-s390x-gnu",1179+ "@rollup/rollup-linux-x64-gnu",1180+ "@rollup/rollup-linux-x64-musl",1181+ "@rollup/rollup-openbsd-x64",1182+ "@rollup/rollup-openharmony-arm64",1183+ "@rollup/rollup-win32-arm64-msvc",1184+ "@rollup/rollup-win32-ia32-msvc",1185+ "@rollup/rollup-win32-x64-gnu",1186+ "@rollup/rollup-win32-x64-msvc",1187+ "fsevents"1188+ ],1189+ "bin": true1190+ },1191+ "semver@6.3.1": {1192+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",1193+ "bin": true1194+ },1195+ "source-map-js@1.2.1": {1196+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="1197+ },1198+ "tinyglobby@0.2.16_picomatch@4.0.4": {1199+ "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",1200+ "dependencies": [1201+ "fdir",1202+ "picomatch@4.0.4"1203+ ]1204+ },1205+ "update-browserslist-db@1.2.3_browserslist@4.28.2": {1206+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",1207+ "dependencies": [1208+ "browserslist",1209+ "escalade",1210+ "picocolors"1211+ ],1212+ "bin": true1213+ },1214+ "vite@7.3.2_picomatch@4.0.4": {1215+ "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==",1216+ "dependencies": [1217+ "esbuild@0.27.7",1218+ "fdir",1219+ "picomatch@4.0.4",1220+ "postcss",1221+ "rollup",1222+ "tinyglobby"1223+ ],1224+ "optionalDependencies": [1225+ "fsevents"1226+ ],1227+ "bin": true1228+ },1229+ "yallist@3.1.1": {1230+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="1231+ }1232+ },1233+ "workspace": {1234+ "dependencies": [1235+ "jsr:@fresh/core@^2.2.2",1236+ "jsr:@fresh/plugin-vite@^1.0.8",1237+ "jsr:@std/assert@^1.0.19",1238+ "npm:@preact/signals@^2.5.0",1239+ "npm:preact@^10.27.2",1240+ "npm:vite@^7.1.3"1241+ ]1242+ }1243+}
A islands/Counter.tsx +16 -0

Not shown: this page already shows 6000 lines of diff.

A islands/ShikakuGame.tsx +414 -0

Not shown: this page already shows 6000 lines of diff.

A lib/date/daily.ts +30 -0

Not shown: this page already shows 6000 lines of diff.

A lib/shikaku/catalog.ts +14 -0

Not shown: this page already shows 6000 lines of diff.

A lib/shikaku/clue_symbol.ts +15 -0

Not shown: this page already shows 6000 lines of diff.

A lib/shikaku/clue_tone.ts +3 -0

Not shown: this page already shows 6000 lines of diff.

A lib/shikaku/engine.ts +111 -0

Not shown: this page already shows 6000 lines of diff.

A lib/shikaku/generator.ts +410 -0

Not shown: this page already shows 6000 lines of diff.

A lib/shikaku/interaction.ts +39 -0

Not shown: this page already shows 6000 lines of diff.

A lib/shikaku/play_state.ts +9 -0

Not shown: this page already shows 6000 lines of diff.

A lib/shikaku/types.ts +150 -0

Not shown: this page already shows 6000 lines of diff.

A lib/site/brand.ts +10 -0

Not shown: this page already shows 6000 lines of diff.

A lib/storage/local_progress.ts +58 -0

Not shown: this page already shows 6000 lines of diff.

A main.ts +30 -0

Not shown: this page already shows 6000 lines of diff.

A routes/_app.tsx +52 -0

Not shown: this page already shows 6000 lines of diff.

A routes/api/[name].tsx +10 -0

Not shown: this page already shows 6000 lines of diff.

A routes/api/puzzles/[date].ts +11 -0

Not shown: this page already shows 6000 lines of diff.

A routes/daily/[date].tsx +69 -0

Not shown: this page already shows 6000 lines of diff.

A routes/daily/index.tsx +13 -0

Not shown: this page already shows 6000 lines of diff.

A routes/index.tsx +58 -0

Not shown: this page already shows 6000 lines of diff.

A static/apple-touch-icon.png +0 -0

Binary file.

A static/favicon.ico +0 -0

Binary file.

A static/icon-192.png +0 -0

Binary file.

A static/icon-512.png +0 -0

Binary file.

A static/icon.svg +77 -0

Not shown: this page already shows 6000 lines of diff.

A static/logo.svg +19 -0

Not shown: this page already shows 6000 lines of diff.

A static/site.webmanifest +30 -0

Not shown: this page already shows 6000 lines of diff.

A tests/lib/date/daily_test.ts +43 -0

Not shown: this page already shows 6000 lines of diff.

A tests/lib/shikaku/catalog_test.ts +26 -0

Not shown: this page already shows 6000 lines of diff.

A tests/lib/shikaku/clue_symbol_test.ts +16 -0

Not shown: this page already shows 6000 lines of diff.

A tests/lib/shikaku/clue_tone_test.ts +8 -0

Not shown: this page already shows 6000 lines of diff.

A tests/lib/shikaku/engine_test.ts +161 -0

Not shown: this page already shows 6000 lines of diff.

A tests/lib/shikaku/generator_test.ts +84 -0

Not shown: this page already shows 6000 lines of diff.

A tests/lib/shikaku/interaction_test.ts +33 -0

Not shown: this page already shows 6000 lines of diff.

A tests/lib/shikaku/play_state_test.ts +16 -0

Not shown: this page already shows 6000 lines of diff.

A tests/lib/shikaku/types_test.ts +44 -0

Not shown: this page already shows 6000 lines of diff.

A tests/lib/site/brand_test.ts +21 -0

Not shown: this page already shows 6000 lines of diff.

A tests/lib/storage/local_progress_test.ts +110 -0

Not shown: this page already shows 6000 lines of diff.

A utils.ts +9 -0

Not shown: this page already shows 6000 lines of diff.

A vite.config.ts +6 -0

Not shown: this page already shows 6000 lines of diff.