Przejdź do treści
Biblioteka skilli
DevOps i chmura · Automatyzacja

deploy

/deploy

Wdraża aplikację crouton na staging Cloudflare Workers z automatycznym tworzeniem D1 i KV, synchronizacją identyfikatorów, migracjami i podpięciem CI; produkcja ma osobny skill.

Repozytorium
nuxt-crouton ↗
Licencja
MIT
Ostatnia zmiana repozytorium
27.10.2026

Ocena i bezpieczeństwo

100/ 100Klasa: dobry
Format25 / 25
Frontmatter z nazwą i opisem, poprawna nazwa, opis do 1024 znaków, nazwa zgodna z folderem.
Odkrywalność25 / 25
Opis mówi, kiedy użyć skilla, ma sensowną długość i jest w 3. osobie.
Treść35 / 35
Co najmniej 150 słów i do 500 linii, nagłówki, listy kroków, przykłady albo kod.
Higiena15 / 15
Bez zaślepek typu TODO, bez ścieżek Windows, z licencją.
Ryzykobrak sygnałów w skanie
Pliki w paczce
1
Skrypty
0
Komentarze HTML
0
Adresy URL w SKILL.md
0
Przestarzałość

Brak sygnałów. Repozytorium zmienione 27.10.2026, bez odwołań do wycofanych modeli i API.

Licencja

MIT, otwarta: można używać i zmieniać, z zachowaniem informacji o autorze.

Co robi i kiedy

Wdraża aplikację crouton na staging Cloudflare Workers z automatycznym tworzeniem D1 i KV, synchronizacją identyfikatorów, migracjami i podpięciem CI; produkcja ma osobny skill.

Oryginalny opis (EN)

Deploy a crouton app to Cloudflare Workers STAGING (auto-provisioning) — the DEFAULT deploy, staging only, never production. Handles the staging bootstrap (auto-creates D1+KV, syncs ids, migrates), wiring CI, routine staging deploys, and Pages→Workers migration. For production use the separate /deploy-production skill. Use when deploying any app in apps/.

Jak działa

  1. Environment & domain convention (133)
  2. Usage
  3. Rules
  4. How the pipeline works (one source of truth)
  5. Workflow
  6. Migrating a Pages app → Workers
  7. Credentials
  8. Troubleshooting
  9. Deploy Learnings Location
Sekcje z nagłówków SKILL.md, w oryginale · 235 linii, 1 924 słów
Podgląd SKILL.md
---
name: deploy
layer: stack
description: Deploy a crouton app to Cloudflare Workers STAGING (auto-provisioning) — the DEFAULT deploy, staging only, never production. Handles the staging bootstrap (auto-creates D1+KV, syncs ids, migrates), wiring CI, routine staging deploys, and Pages→Workers migration. For production use the separate /deploy-production skill. Use when deploying any app in apps/.
allowed-tools: Bash, Read, Grep, Glob, Edit, Agent, AskUserQuestion
---

# Deploy Skill — Cloudflare Workers

Deploys a crouton app to **Cloudflare Workers (static assets)** — the crouton
deploy standard (#108). Wrangler **auto-provisions** the app's D1 + KV on the
first deploy, so there's no manual resource/project creation, no id-juggling.

> **🟦 STAGING ONLY — this skill never deploys to production.** "Deploy" defaults to
> **staging** here. Shipping to production is a deliberate, human-initiated action handled
> by the separate **`/deploy-production`** skill. Never deploy production as part of routine work.

> **Not Cloudflare Pages.** We do NOT use `wrangler pages …`, `pages_build_output_dir`,
> or the Pages "strip env" step anymore. If you find those, the app is on the old
> Pages path — see **Migrating a Pages app → Workers** below.

## Environment & domain convention (#133)

Two environments, two domains — kept on **separate registrable domains** so a
staging session can never authenticate against production (cookie isolation):

| Env | wrangler env | Worker | Domain |
|-----|--------------|--------|--------|
| **production** | top-level | `<app>` | `<app>.friendlyinter.net` |
| **staging** | `env.staging` | `<app>-staging` | `<app>.pmcp.dev` (public) |

The deploy-env is named **`staging`** (not `preview`): scripts are `cf:staging` /
`db:migrate:staging`, deploys use `--env staging`. (The general `crouton` CLI stays
domain-agnostic via `--domain <zone>`; the friendlyinter.net/pmcp.dev split is this
monorepo's convention, applied per app at its production cutover — #136 for triage.)

## Usage

```
/deploy              # Deploy current app to STAGING (auto-detected from cwd)
/deploy velo         # Deploy a specific app to STAGING
# production → use the separate /deploy-production skill
```

## Rules

1. **STAGING ONLY.** This skill deploys to **staging**, never production (that's the separate `/deploy-production` skill). Always confirm the target app first.
2. **Workers, not Pages** — `NITRO_PRESET=cloudflare_module`, output in `.output/`, deploy with `wrangler deploy` (never `wrangler pages deploy`).
3. **NEVER manually create D1/KV** — they auto-provision from the **id-less** `wrangler.jsonc` on first deploy. After provisioning, run `sync:ids` and **commit** the written-back ids (remote `d1 migrations apply` needs them — workers-sdk#13632).
4. **NEVER skip `nuxt prepare` before build** in CI — rolldown tsconfig bug. (Locally, the `cf:*` scripts assume `node_modules`/`.nuxt` are prepared from `pnpm install`.)
5. **`hub: { db: 'sqlite' }`** — never `hub: { database: true }`.
6. **`postinstall` must be guarded** — `nuxt prepare 2>/dev/null || true`, never bare (a bare prepare aborts the whole-monorepo install and fails every app's deploy).

## How the pipeline works (one source of truth)

The deploy logic lives in the app's **`package.json` scripts** — the same commands
you run locally and that CI runs. Don't reinvent them step-by-step:

- **`cf:deploy`** (production — run **only** via the `/deploy-production` skill): `build → wrangler deploy (auto-provision) → sync:ids → d1 migrations apply --remote`
- **`cf:staging`** (isolated staging env): `build → inject-wrangler-env → wrangler deploy --env staging → sync:ids → inject-wrangler-env → d1 migrations apply --env staging --remote`
- **`sync:ids`** — queries wrangler, writes provisioned ids back into `wrangler.jsonc`
- **`db:migrate` / `db:migrate:prod` / `db:migrate:staging`** — D1 migrations (local / remote / staging-remote)

A freshly scaffolded app (`crouton init`) already ships all of this:
`wrangler.jsonc` (id-less), `scripts/sync-wrangler-ids.mjs`,
`scripts/inject-wrangler-env.mjs`, `drizzle.config.ts`, the chained scripts, the
CF stubs + nitro aliases, and the guarded postinstall.

## Workflow

### Step 1: Detect app
- arg → `apps/{arg}/`; else if cwd is inside an app → that app; else ask.
- Verify it has `wrangler.jsonc` + `package.json`.

### Step 2: Pre-flight (run in parallel)
Confirm the app is Workers-ready:
1. **`wrangler.jsonc`** present, **Workers-style** (has `compatibility_flags: ["nodejs_compat"]`, `d1_databases`/`kv_namespaces`; **no** `pages_build_output_dir`).
2. **Scripts** `scripts/sync-wrangler-ids.mjs` + `scripts/inject-wrangler-env.mjs` exist.
3. **`drizzle.config.ts`** exists (so `db:generate` works).
4. **Package scripts** — `cf:deploy` is the Workers chain; `postinstall` is guarded.
5. **CF stubs** — `server/utils/_cf-stubs/` exists; `nuxt.config.ts` has `nitro.alias` for passkey/webauthn/papaparse stubs and pins **no** preset.
6. **Auth** — `CLOUDFLARE_ACCOUNT_ID` + `CLOUDFLARE_API_TOKEN` available in the environment (see **Credentials**).

If anything is missing and the app is on the old Pages setup → **Migrating a Pages app → Workers**. If it's just missing files, copy them from `apps/velo` (the reference) or re-run the scaffolder.

### Step 3: First (bootstrap) staging deploy
The id-less bindings auto-provision here. Confirm with the user, then deploy the
isolated **staging** environment (its own auto-provisioned D1+KV):

```bash
cd apps/{app}
pnpm cf:staging     # provisions + deploys the *-staging worker, migrates --env staging
```

Then **commit the written-back ids** (bootstrap → committed):
```bash
git add apps/{app}/wrangler.jsonc && git commit -m "chore({app}): commit provisioned staging D1/KV ids"
```

> The **production** bootstrap (`cf:deploy`, prod D1+KV, `<app>.friendlyinter.net`) is a
> deliberate, separate step — see the **`/deploy-production`** skill. This skill stops at staging.

> If you're an agent **without Cloudflare egress** (sandbox), you can't run these —
> verify what's verifiable (config, `pnpm sync:ids --dry-run` logic) and have the
> user run the CF-gated steps, pasting output (the #109/#113/#114 loop).

### Step 4: Wire CI (opt in via `deploy.config.json`)
There is **one generic workflow for all apps** — `.github/workflows/deploy-apps.yml`
(#481/#638; the old per-app `deploy-<app>.yml` callers are retired — don't create one).
An app opts in by adding a `deploy.config.json` next to its `package.json`. **Model on
`apps/velo/deploy.config.json`.** Set: `stagingUrl`, `productionUrl` and `layerPackages`.
Do **not** write a `watchPaths` list: the workflow's `detect` job derives it from the app's
`package.json` — the app dir, the lockfile and every `@fyit/*` dependency, transitively
(#2397) — so adding a package to the app is enough. `watchPaths` is only for paths that
can't be derived (rare). `detect` then fans out one reusable `deploy-app.yml` call per
affected app. Merge to `main`/open a PR → isolated staging
with the URL commented on the PR; manual dispatch (app + environment inputs) →
production (#347). The fan-out uses `secrets: inherit`.

Ensure **repo-level** secrets `CLOUDFLARE_ACCOUNT_ID` + `CLOUDFLARE_API_TOKEN` exist
(Settings → Secrets and variables → Actions).

### Step 4.5: App (Worker) secrets
The app's own secrets (`BETTER_AUTH_SECRET`/`BETTER_AUTH_URL`, `NUXT_*`, etc.) live
on the **Worker**, NOT in `wrangler.jsonc`. **Worker secrets persist across deploys**,
so this is a one-time bootstrap per worker (prod + staging), not a per-deploy step.

Two ways:
- **Manual (one-time):** `npx wrangler secret bulk secrets.json` (prod) /
  `… --env staging` (staging). `BETTER_AUTH_URL`/`BASE_URL` must be the **production
  domain** (not localhost). Pages secrets do NOT carry over — re-provide the values.
- **Automatic (CI):** store the whole bundle as a **repository-level** Actions secret
  `WORKER_SECRETS_JSON` (a JSON object of `{ "NAME": "value", … }`). It MUST be
  repo-level, NOT an Environment secret — the deploy job is reached via
  `secrets: inherit` from caller jobs that declare no `environment:`, so an
  Environment-scoped secret resolves EMPTY with no error and the Worker deploys
  without secrets (#1094). The reusable `deploy-app.yml` runs `wrangler secret bulk`
  from it on every deploy (`--env staging` for non-prod). Omit it to manage secrets
  manually. If the app depends on the bundle, set `"secrets": { "required": true }`
  in its `deploy.config.json` — an empty resolution then FAILS the deploy instead
  of silently skipping. Automation can't invent values — they must live in that
  secret once.

### Step 5: Routine deploys (staging)
- **CI (preferred):** merge to `main` (or open a PR) → the caller runs the staging pipeline (#347).
- **Local:** `pnpm cf:staging` from the app dir.
- **Production is never routine** — ship it deliberately via the **`/deploy-production`** skill.

### Demo data on staging (#2366)
Every **staging** and PR-preview deploy runs `crouton-seed` itself, once (the *Seed collection + demo data* (#1370)
step in `deploy-app.yml`), so the app gets its packages' demo data and the `test1` team the
review login joins — **no seed line in the app's `cf:staging` script**. The app only needs
`@fyit/crouton-cli` as a dependency. Opt out with `"seed": false` in `deploy.config.json`.
A failed seed warns on the run; it never fails the deploy. Production never seeds.

### Apps without a database or sign-in (#2377)
A standalone viewer (e.g. `pocs/loop-station`: no NuxtHub, no D1, no auth) deploys through the
same pipeline: the PR preview skips the D1 provision/migrate when the built config declares no
database, and `"reviewLogin": false` in `deploy.config.json` skips the review login + email and
turns the smoke into a plain "page answers 200" check. Without NuxtHub, set
`nitro.cloudflare.deployConfig: true` so the build writes `.output/server/wrangler.json`, which the
PR preview rewrites. Put any pre-build data step in a `build:before` hook, not only in `package.json`
scripts — the PR preview runs a bare `nuxt build`.

### Auto-seeded review login on staging previews (#608)
Every **staging** deploy auto-seeds a throwaway, loginable test account on the
preview's isolated D1 so a reviewer can open the URL and be **inside the app in one
step** — no register → create-team wall. `deploy-app.yml` runs
`scripts/seed-review-login.mjs` against the deployed Worker (the app's own
`/api/auth/sign-up/email` + a team via `organization/create` when the app doesn't
auto-make one). The PR's staging comment only says the login exists — the password
and the one-click sign-in link (which carries it) are **emailed to the owner** (Resend;
`vars.REVIEW_LOGIN_EMAIL`, else `vars.DIGEST_REPORT_EMAIL`), never posted: PR comments
and run summaries are public on this repo (#2358). Creds are **deterministic per
preview** (redeploys reuse the same login, no user pile-up), derived from the
**required** repo secret `REVIEW_SEED_SECRET` — no fallback salt; unset → no review
login. A rotated secret resets the existing account's password on the next deploy.
The step is best-effort (never fails the deploy); **production seeds nothing**.

## Migrating a Pages app → Workers

For an app still on the Pages setup (`wrangler.toml`, `pages_build_output_dir`,
`wrangler pages deploy`):

1. **`wrangler.toml` → `wrangler.jsonc`** in the Workers shape (see `apps/velo`):
   drop `pages_build_output_dir`; keep `name`/`compatibility_*`; `d1_databases` (reuse
   the existing prod `database_id`), `kv_namespaces`; add an `env.staging` block with a
   **separate** `{app}-staging-db` + KV (id-less to auto-provision, or existing staging ids).
2. **Add** `scripts/sync-wrangler-ids.mjs`, `scripts/inject-wrangler-env.mjs`,
   `drizzle.config.ts` (copy from `apps/velo`).
3. **package.json** — replace the Pages `cf:*` scripts with the Workers chain
   (`NITRO_PRESET=cloudflare_module`, `sync:ids`, `db:migrate:staging`); keep the
   guarded `postinstall`.
4. **nuxt.config.ts** — remove `nitro.preset: 'cloudflare-pages'` (keep the `nitro.alias` stubs).
5. **CI** — replace `deploy-{app}.yml` (+ any `-preview.yml`) with the thin caller from Step 4; delete the Pages strip-env step (not needed on Workers).
6. **Deploy + commit ids** as in Step 3.

## Credentials

The job/shell needs **`CLOUDFLARE_ACCOUNT_ID`** + **`CLOUDFLARE_API_TOKEN`**.

- **`CLOUDFLARE_ACCOUNT_ID`** — dashboard → Workers & Pages → Account ID (also the hex in the dashboard URL). Not secret.
- **`CLOUDFLARE_API_TOKEN`** — My Profile → API Tokens → **Create Custom Token**. For Workers + **auto-provisioning** the token needs (Account-scoped):
  - **Workers Scripts: Edit**
  - **D1: Edit**
  - **Workers KV Storage: Edit**
  - (**Workers R2 Storage: Edit** if the app uses blob)

  Cloudflare shows a token's value **only once**, and GitHub never reveals a saved
  secret — so mint a fresh dedicated token rather than reusing one.

> Note: this differs from the old Pages token (which used *Cloudflare Pages: Edit*).
> A Pages-only token will fail to auto-provision D1/KV.

## Troubleshooting

### `Couldn't find a D1 DB … missing database_id` (on migrate)
The first deploy provisioned the DB but the id isn't in `wrangler.jsonc` yet. Run
`pnpm sync:ids` (after a deploy) and commit the result. `cf:deploy`/`cf:staging` do
this automatically.

### `Configuration file does not support "env"` / redirected config rejects env
Wrangler 4.64+ rejects `env` in a *redirected* config. `scripts/inject-wrangler-env.mjs`
(run by `cf:staging`) re-injects `env` into `.output/server/wrangler.json` and removes
the redirect so `--env staging` deploys read it directly. No manual strip step.

### `papaparse` RollupError / passkey/tsyringe errors
Add the CF stubs + `nitro.alias` (see scaffolder output / `apps/velo`).

### KV namespace not found by `sync:ids`
It matches the auto-provisioned title `<worker-name>-<binding>` (e.g.
`{app}-KV`, `{app}-staging-KV`). The script logs the available titles if no match —
adjust only if your account names them differently.

### Build OOM
Set `NODE_OPTIONS='--max-old-space-size=8192'` (CI sets this).

## Deploy Learnings Location
Per-app deploy gotchas: `docs/projects/{app}/{app}-deploy.md`. Append new fixes there.
Reference implementation for everything above: **`apps/velo`**.

Wersje

RepozytoriumWynikLicencja
Ta strona · friendlyinternet/nuxt-crouton100MIT
jeremylongshore/tons-of-skills-marketplace100MIT
zeitlos/lucity100AGPL-3.0
microsoft/power-platform-skills100MIT
jikig-ai/soleur100Apache-2.0
curiositech/windags-skills100Apache-2.0
shakestzd/htmlgraph100MIT
microsoft/power-platform-skills100MIT
jazzyalex/agent-sessions100MIT

Migawka bazy z 28.10.2026 · wersja paczki 00428758d716 (skrót SHA-256 całej paczki)

Pobrania w ostatnich 30 dniach: 0 · ranking

Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.

Podobne skille

  • 100cloudflare
    Wdraża aplikację Vibes na Cloudflare Workers przez Deploy API.
  • 100cloudflare-deploy
    Wdraża aplikacje i infrastrukturę na Cloudflare przez Workers, Pages i powiązane usługi platformy.
  • 95Cloudflare
    Wdraża aplikacje Workers i Pages w Cloudflare i wskazuje, gdzie szukać dokumentacji.
  • 100cloudflare-deploy
    Wdraża aplikacje i infrastrukturę na Cloudflare z użyciem Workers, Pages i powiązanych usług platformy.
  • 100crouton-ci-and-deploy-map
    Przedstawia mapę workflowów GitHub i potoku wdrożeniowego nuxt-crouton: co bramkuje każdy workflow, jak merge trafia na Cloudflare i gdzie są sekrety.
  • 100cloudflare-deploy
    Wdraża aplikacje i infrastrukturę na Cloudflare z użyciem Workers, Pages i powiązanych usług platformy.

Uwagi i zgłoszenia

Wiadomość trafi do Bartosza Sokolińskiego. Adres e-mail jest potrzebny tylko do odpowiedzi. Szczegóły w polityce prywatności.