@getvitops/create 0.7.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/CHANGELOG.md +443 -6
  2. package/package.json +2 -3
  3. package/templates/emdash/.agents/skills/promote/SKILL.md +24 -7
  4. package/templates/emdash/.astro/types.d.ts +3 -0
  5. package/templates/emdash/.claude/hooks/session-start.sh +0 -0
  6. package/templates/emdash/.github/workflows/backmerge.yml +18 -0
  7. package/templates/emdash/.github/workflows/deploy-prod.yml +1 -1
  8. package/templates/emdash/.github/workflows/refresh-dev.yml +25 -0
  9. package/templates/emdash/.node-version +1 -0
  10. package/templates/emdash/AGENTS.md +51 -9
  11. package/templates/emdash/README.md +15 -4
  12. package/templates/emdash/SETUP.html +103 -0
  13. package/templates/emdash/astro.config.mjs +47 -4
  14. package/templates/emdash/package.json +15 -11
  15. package/templates/emdash/pnpm-lock.yaml +183 -0
  16. package/templates/emdash/pnpm-workspace.yaml +1 -1
  17. package/templates/emdash/public/_headers +10 -0
  18. package/templates/emdash/scripts/build-dev-wrangler.mjs +6 -0
  19. package/templates/emdash/scripts/refresh-dev.mjs +182 -0
  20. package/templates/emdash/seed/seed.json +104 -5
  21. package/templates/emdash/site.json +77 -2
  22. package/templates/emdash/src/layouts/Layout.astro +7 -1
  23. package/templates/emdash/src/pages/404.astro +5 -0
  24. package/templates/emdash/src/pages/[...slug].astro +15 -2
  25. package/templates/emdash/src/pages/index.astro +15 -2
  26. package/templates/emdash/vite.config.ts +18 -4
  27. package/templates/emdash/wrangler.jsonc +4 -0
  28. package/templates/static/.github/workflows/backmerge.yml +18 -0
  29. package/templates/static/.github/workflows/deploy-prod.yml +1 -1
  30. package/templates/static/.node-version +1 -0
  31. package/templates/static/AGENTS.md +9 -9
  32. package/templates/static/SETUP.html +103 -0
  33. package/templates/static/package.json +6 -6
  34. package/templates/static/pnpm-workspace.yaml +21 -0
  35. package/templates/static/public/_headers +10 -0
  36. package/templates/static/site.json +2 -2
@@ -19,6 +19,16 @@ styled by the Vitops design system.
19
19
  `getEmDashCollection` / `getEmDashEntry` from `emdash`; render Portable Text
20
20
  with `<PortableText />` from `emdash/ui` (the Vitops blocks from
21
21
  `@getvitops/emdash` are merged in automatically).
22
+ - **Building pages from patterns:** the editor's insert menu offers the `vitops.*` blocks —
23
+ link/button, image compare, copy snippet, banner, disclosure, accordion, hero, carousel, gallery,
24
+ cards, marquee (`npx vitops docs blocks` lists them with every field). Repeating content (cards, gallery images, accordion items, carousel slides) is
25
+ a repeater field. A block cannot contain other blocks, and a `vitops.*` block inside EmDash's
26
+ built-in `columns` does not render — for layout (a section, a split, a hero) use a `blocks`
27
+ field, or hand-write the page template with `@getvitops/astro` components
28
+ (`Subgrid`, `Cards`, `Carousel`, …). `npx vitops docs components` lists every pattern, which
29
+ tiers provide it, and which block renders it. Override a block's rendering per site with
30
+ `<PortableText components={{ type: { 'vitops.cards': MyCards } }} />`; hide one with
31
+ `vitopsEmdash({ blocks: { exclude: [...] } })` in `astro.config.mjs`.
22
32
  - `seed/seed.json` only applies against an empty database: structure
23
33
  (collections, menus, settings) on first boot; the `content` entries only
24
34
  when the setup wizard's "include sample content" option is chosen. Changing
@@ -30,15 +40,16 @@ styled by the Vitops design system.
30
40
  full generated class-vocabulary reference to this file.
31
41
  - **Layout foundations — these are the answer, not a starting point.** Six
32
42
  substitutions carry the structure of nearly every page:
33
- | About to write… | Write instead |
34
- | --- | --- |
35
- | a `wrap`/`wrapper`/`container`/`inner` class | **`centered`** |
36
- | `max-width` + `margin-inline: auto` | **`centered`** |
37
- | `padding-block` on a section | **`region`** |
38
- | margins between headings/paragraphs/lists | **`rhythm`** |
39
- | `display: grid` + `grid-template-columns: repeat(n, …)` | **`subgrid`** |
40
- | `repeat(auto-fit, minmax(…))` | **`grid-auto`** |
41
- | `display: flex` + `gap` for a row of controls | **`cluster`** |
43
+
44
+ | About to write… | Write instead |
45
+ | ------------------------------------------------------- | --------------- |
46
+ | a `wrap`/`wrapper`/`container`/`inner` class | **`centered`** |
47
+ | `max-width` + `margin-inline: auto` | **`centered`** |
48
+ | `padding-block` on a section | **`region`** |
49
+ | margins between headings/paragraphs/lists | **`rhythm`** |
50
+ | `display: grid` + `grid-template-columns: repeat(n, …)` | **`subgrid`** |
51
+ | `repeat(auto-fit, minmax(…))` | **`grid-auto`** |
52
+ | `display: flex` + `gap` for a row of controls | **`cluster`** |
42
53
 
43
54
  `centered` is a grid of _named tracks_, not a max-width box — a child widens
44
55
  itself with `breakout`/`spotlight`/`fullbleed` without the parent knowing, which
@@ -105,11 +116,42 @@ styled by the Vitops design system.
105
116
  the fields its forms collect, where it deploys — rather than from guesses.
106
117
  It still needs review before launch.
107
118
 
119
+ ## EmDash 1.x behaviours worth knowing
120
+
121
+ - **Passkeys are bound to the hostname they were created on.** After the
122
+ workers.dev → custom-domain cutover, use **Settings → General → Change
123
+ domain**, then **Continue on** to add a passkey at the new address.
124
+ - **HTML blocks created in the admin run JavaScript** in a sandboxed iframe
125
+ (Contributor and up can add it). Astro's `security.csp` blocks their styles
126
+ and scripts, so don't turn CSP on without allowing for that.
127
+ - **Link entries by `entry.data.slug`, never `entry.id`** — on multilingual
128
+ sites `id` carries a locale prefix.
129
+ - **Submit `/sitemap.xml`** to search engines, not a per-collection sitemap;
130
+ collection sitemaps now split into pages of 2,000 entries.
131
+ - **A stuck D1 migration lock** is cleared with
132
+ `pnpm exec emdash migrate --take-over-lock <id>` (confirms the target, or
133
+ needs `--expected-target-fingerprint` non-interactively).
134
+
108
135
  ## Docs MCP servers
109
136
 
110
137
  `.mcp.json` preconfigures the Astro docs and EmDash docs MCP servers — prefer
111
138
  searching them over pre-trained knowledge for Astro/EmDash questions.
112
139
 
140
+ ## EmDash agent skills
141
+
142
+ The EmDash skills (`building-emdash-site`, `creating-plugins`, `emdash-cli`,
143
+ `upgrading-emdash` and the two WordPress porting skills) are installed per
144
+ project, not globally, so they match the `emdash` version this repo pins. If
145
+ `.agents/skills/building-emdash-site/` is missing, install them (the setup guide
146
+ and `SETUP.html` have the full step):
147
+
148
+ ```bash
149
+ npx skills add emdash-cms/skills --skill '*' -a claude-code -y
150
+ ```
151
+
152
+ Refresh them with `npx skills update` after bumping `emdash` — the
153
+ `upgrading-emdash` skill covers the rest of the upgrade.
154
+
113
155
  ## Commands
114
156
 
115
157
  - `pnpm dev` — local dev with local D1/R2 emulation (no Cloudflare account)
@@ -14,7 +14,8 @@ Scaffolded from `vp create @getvitops:emdash`.
14
14
  (Tailwind v4 format), generates favicons/PWA assets from
15
15
  `src/assets/logo.svg`, and serves the web-component runtime
16
16
  - **`@getvitops/emdash`** — design-system Portable Text blocks in the editor
17
- slash menu: image compare, copy snippet, banner, disclosure, carousel
17
+ slash menu (hero, cards, accordion, carousel, gallery, marquee, banner, …);
18
+ `npx vitops docs blocks` lists every block and field
18
19
 
19
20
  `src/assets/placeholder/` ships neutral wireframe images for layout work
20
21
  before real imagery exists — delete once real assets land (separate from
@@ -27,6 +28,11 @@ pnpm install
27
28
  pnpm dev
28
29
  ```
29
30
 
31
+ Once this is its own repo (not sitting inside the `getvitops/design-system`
32
+ monorepo), uncomment `lint.options` in `vite.config.ts` for type-aware
33
+ `vp check`/`vp lint` — it ships commented out because vite-plus 1.0 only
34
+ honours that option at a project's actual root, and errors on it otherwise.
35
+
30
36
  No Cloudflare account needed: `astro dev` runs the Worker locally with local
31
37
  D1/R2 emulation (state in `.wrangler/`). On first boot EmDash runs its
32
38
  migrations and applies the structure from `seed/seed.json` — a `pages`
@@ -82,7 +88,8 @@ The repo ships a two-environment flow modeled on branch = environment:
82
88
  into `main` with auto-merge enabled. With required reviews on `main`, a
83
89
  human approves the PR; merging deploys prod.
84
90
 
85
- One-time setup — work through the checklist:
91
+ One-time setup — see [Start a new EmDash site](https://docs.vitops.ca/guides/new-emdash-site) for the whole
92
+ procedure, then work through the checklist:
86
93
 
87
94
  ```bash
88
95
  pnpm run sop && open SETUP.html # or: xdg-open SETUP.html
@@ -113,12 +120,12 @@ is a configurable dimension of the project, not a rewrite:
113
120
  - **`node`** — `@astrojs/node` (standalone) + SQLite file + local uploads,
114
121
  for a VPS / docker-compose / k8s host. Not installed by default; to switch:
115
122
  `pnpm add @astrojs/node better-sqlite3`, then `vitopsHosting({ target:
116
- 'node' })` (or set `HOSTING=node` — the env var wins). Run the built site
123
+ 'node' })` (or set `HOSTING=node` — the env var wins). Run the built site
117
124
  with `node ./dist/server/entry.mjs`; data lives in `./data/` (gitignored) —
118
125
  persist it as a volume. Scheduled publishing runs in-process on Node, so
119
126
  the worker/cron pieces aren't needed. For production, move storage to
120
127
  S3-compatible and/or the database to Postgres via `vitopsHosting({ node:
121
- { database, storage } })`. CI deploy for Node hosts is TBD — the shipped
128
+ { database, storage } })`. CI deploy for Node hosts is TBD — the shipped
122
129
  workflows are Cloudflare-specific.
123
130
 
124
131
  Moving an existing site between targets (either direction) is a data
@@ -134,6 +141,10 @@ and media in the storage backend (bucket/directory copy).
134
141
  - **Skills** (`.agents/skills/`): `promote` dispatches the dev → main
135
142
  promotion workflow. Run `npx vitops agents` to also write the design-system
136
143
  class reference into `AGENTS.md`.
144
+ - **EmDash skills** are installed per project so they match the pinned `emdash`
145
+ version: `npx skills add emdash-cms/skills --skill '*' -a claude-code -y`,
146
+ then commit `.agents/skills/` and `skills-lock.json`. Update with
147
+ `npx skills update` after an `emdash` bump.
137
148
  - **Claude Code on the web**: the SessionStart hook
138
149
  (`.claude/hooks/session-start.sh`) installs Node 24 (matching
139
150
  `devEngines`), activates the pinned pnpm, and installs dependencies in the
@@ -159,6 +159,94 @@
159
159
  this exists.
160
160
  </span>
161
161
  </label>
162
+ <label class="custom-check">
163
+ <input type="checkbox" data-sop="hosting.emdash-fingerprint" />
164
+ <span class="custom-check__box"
165
+ ><span class="custom-check__indicator custom-check__indicator--check"></span
166
+ ></span>
167
+ <span>
168
+ <strong>(EmDash template)</strong> After the first deploy to each environment, run
169
+ <code>npx emdash migrate --status</code> locally against that environment's real
170
+ database, review the printed account/database identity, and set the reviewed
171
+ fingerprint:
172
+ <code
173
+ >gh variable set EMDASH_TARGET_FINGERPRINT --env dev --body &lt;value&gt;</code
174
+ >
175
+ and again with <code>--env production</code>. No command can do this for you — it's
176
+ the human review the fingerprint guard exists for. Deploys fail clearly on the
177
+ migration-apply step until it's set for that environment.
178
+ </span>
179
+ </label>
180
+ <label class="custom-check">
181
+ <input type="checkbox" data-sop="hosting.design-system-editor-token" />
182
+ <span class="custom-check__box"
183
+ ><span class="custom-check__indicator custom-check__indicator--check"></span
184
+ ></span>
185
+ <span>
186
+ <strong>(EmDash template, only if <code>designSystemEditor</code> is on)</strong>
187
+ Create a fine-grained GitHub PAT scoped to this one repository,
188
+ <code>Contents: Read and write</code> only — no <code>admin</code> scope, no access
189
+ to any other repo — then <code>gh secret set VITOPS_GITHUB_TOKEN</code>. Also set
190
+ <code>site.deployment.repo</code> (<code>"owner/name"</code>) and
191
+ <code>site.deployment.branch</code> (default <code>"dev"</code>) in
192
+ <code>site.json</code>. Without these the live design-system editor still works —
193
+ only the auto-commit-to-source half is skipped, and the admin page's response says
194
+ so.
195
+ </span>
196
+ </label>
197
+ <label class="custom-check">
198
+ <input type="checkbox" data-sop="hosting.content-in-prod" />
199
+ <span class="custom-check__box"
200
+ ><span class="custom-check__indicator custom-check__indicator--check"></span
201
+ ></span>
202
+ <span>
203
+ <strong>Know where content is edited (EmDash template).</strong> Editors work on the
204
+ <em>production</em> site — drafts, "Publish changes" and preview links are the
205
+ staging step. The dev site holds a disposable copy of production's database; it is
206
+ refreshed from prod and never promoted back. Code, pages and
207
+ <code>site.json</code> still go dev → main.
208
+ </span>
209
+ </label>
210
+ <label class="custom-check">
211
+ <input type="checkbox" data-sop="hosting.refresh-dev" />
212
+ <span class="custom-check__box"
213
+ ><span class="custom-check__indicator custom-check__indicator--check"></span
214
+ ></span>
215
+ <span>
216
+ EmDash template: run <strong>Refresh dev from prod</strong> (Actions tab) once the
217
+ prod site has content, and again before rehearsing a schema change. It runs weekly
218
+ on its own. To copy media as well, set <code>R2_ACCESS_KEY_ID</code> and
219
+ <code>R2_SECRET_ACCESS_KEY</code> (an R2 API token's S3 credentials) as repo
220
+ secrets; without them only the database is refreshed.
221
+ </span>
222
+ </label>
223
+ <label class="custom-check">
224
+ <input type="checkbox" data-sop="hosting.magic-link" />
225
+ <span class="custom-check__box"
226
+ ><span class="custom-check__indicator custom-check__indicator--check"></span
227
+ ></span>
228
+ <span>
229
+ EmDash template: onboard the sender domain for sign-in email —
230
+ <code>npx vitops email setup send.&lt;your-domain&gt;</code>, then put that address
231
+ in <code>cloudflareEmail({ from })</code> in <code>astro.config.mjs</code> (it ships
232
+ a placeholder). Editors sign in with a magic link ("Sign in with email" on the login
233
+ page) because a passkey only works at the origin it was registered on, so a
234
+ refreshed dev site has no other way in. Check <strong>Settings → Email</strong> and
235
+ send the test email on both prod and dev.
236
+ </span>
237
+ </label>
238
+ <label class="custom-check">
239
+ <input type="checkbox" data-sop="hosting.preview-secret" />
240
+ <span class="custom-check__box"
241
+ ><span class="custom-check__indicator custom-check__indicator--check"></span
242
+ ></span>
243
+ <span>
244
+ EmDash template: set a different <code>EMDASH_PREVIEW_SECRET</code> on the dev
245
+ worker (<code>wrangler secret put EMDASH_PREVIEW_SECRET</code>). The secret lives in
246
+ the database, so a refresh copies prod's — and prod preview links would then open
247
+ drafts on dev.
248
+ </span>
249
+ </label>
162
250
  </div>
163
251
  </details>
164
252
 
@@ -326,6 +414,21 @@
326
414
  <code>npx vitops setup ads</code>.
327
415
  </span>
328
416
  </label>
417
+ <label class="custom-check">
418
+ <input type="checkbox" data-sop="connections.email" />
419
+ <span class="custom-check__box"
420
+ ><span class="custom-check__indicator custom-check__indicator--check"></span
421
+ ></span>
422
+ <span>
423
+ If <code>site.notifications.email</code> sends mail, onboard its sender domain:
424
+ <code>npx vitops email setup --dry</code>, then <code>npx vitops email setup</code>.
425
+ Cloudflare onboards an exact name — usually a subdomain like
426
+ <code>send.&lt;domain&gt;</code>, not the apex — so a mismatch here is silent at
427
+ build time and only fails when a form is actually submitted in production. Both
428
+ templates' <code>deploy</code> script already runs
429
+ <code>vitops email check</code> first as a non-blocking warning.
430
+ </span>
431
+ </label>
329
432
  <label class="custom-check">
330
433
  <input type="checkbox" data-sop="connections.manual" />
331
434
  <span class="custom-check__box"
@@ -1,8 +1,18 @@
1
1
  import react from '@astrojs/react';
2
+ import { cloudflareEmail } from '@emdash-cms/cloudflare/plugins';
2
3
  import vitops from '@getvitops/astro';
4
+ import { resolveOrganizationName } from '@getvitops/astro/routes';
3
5
  import { vitopsEmdash, vitopsHosting } from '@getvitops/emdash';
4
6
  import { defineConfig } from 'astro/config';
5
7
  import emdash from 'emdash/astro';
8
+ import config from './site.json' with { type: 'json' };
9
+
10
+ // site.json's organization.name is the one build-time-readable source for a
11
+ // display name — EmDash's own getSiteSettings() only resolves inside a live
12
+ // Worker request (AsyncLocalStorage + a DB binding), so it can't be read here
13
+ // even though it's what Layout.astro shows on rendered pages. See AGENTS.md's
14
+ // "EmDash plugin as the design-system editing surface".
15
+ const organizationName = resolveOrganizationName(config) ?? 'My EmDash Site';
6
16
 
7
17
  // Hosting seam: adapter + EmDash database/storage for the configured target.
8
18
  // Default 'cloudflare' (Workers + D1 + R2 — see wrangler.jsonc / src/worker.ts).
@@ -26,16 +36,49 @@ export default defineConfig({
26
36
  emdash({
27
37
  database,
28
38
  storage,
29
- // Vitops design-system blocks (image compare, copy snippet, banner,
30
- // disclosure, carousel) in the editor slash menu. Default 'integration'
39
+ // Vitops design-system blocks (link/button, image compare, copy snippet,
40
+ // banner, disclosure, accordion, hero, carousel, gallery, cards, marquee) in the
41
+ // editor slash menu. Narrow them with `vitopsEmdash({ blocks: { exclude } })`. Default 'integration'
31
42
  // script delivery: Layout.astro renders <Head /> from @getvitops/astro,
32
43
  // which emits the web-component runtime tags.
33
- plugins: [vitopsEmdash()],
44
+ //
45
+ // designSystemEditor mounts a live <wc-theme-editor> admin page at
46
+ // /design-system — edits are visible site-wide immediately (no
47
+ // rebuild) and auto-sync back to source once site.deployment.repo and
48
+ // a VITOPS_GITHUB_TOKEN secret are set (see SETUP.html) — see
49
+ // AGENTS.md's "EmDash plugin as the design-system editing surface".
50
+ // Until then the live half still works; only the sync half is skipped.
51
+ //
52
+ // cloudflareEmail sends magic-link sign-in, invites and account recovery
53
+ // through Cloudflare Email Sending (the EMAIL binding in wrangler.jsonc).
54
+ // Magic link is how an editor gets into a site whose database was copied
55
+ // from another origin: a passkey only works at the origin it was
56
+ // registered on, so a dev database refreshed from prod
57
+ // (scripts/refresh-dev.mjs) would otherwise lock everyone out of dev. The
58
+ // cloned users already exist, so the same email signs in on both origins.
59
+ // `from` must be on a domain onboarded with Cloudflare Email Sending —
60
+ // `npx vitops email setup send.<your-domain>` — and is usually the
61
+ // subdomain, not the apex (see AGENTS.md's "Sender-domain onboarding").
62
+ // Without it, magic link answers "Email is not configured".
63
+ plugins: [
64
+ vitopsEmdash({ designSystemEditor: { config } }),
65
+ cloudflareEmail({
66
+ from: { email: 'cms@send.my-emdash-site.example.com', name: organizationName },
67
+ }),
68
+ ],
69
+ // 1.0's runtime migration mode defaults to 'auto' (apply pending core
70
+ // migrations on first request) — fine for local dev, but a deploy
71
+ // should have already migrated before traffic arrives. 'check' 503s a
72
+ // request instead of migrating behind it if the explicit `emdash
73
+ // migrate` step in site-deploy-emdash.yml (see AGENTS.md's CI/CD
74
+ // section) was skipped or failed. `dev: 'auto'` keeps the convenient
75
+ // first-run behaviour for `pnpm dev`.
76
+ migrations: { runtime: 'check', dev: 'auto' },
34
77
  }),
35
78
  vitops({
36
79
  favicon: {
37
80
  source: 'src/assets/logo.svg',
38
- name: 'My EmDash Site',
81
+ name: organizationName,
39
82
  themeColor: '#2e9b73',
40
83
  backgroundColor: '#ffffff',
41
84
  },
@@ -7,8 +7,8 @@
7
7
  "dev": "astro dev",
8
8
  "build": "astro build",
9
9
  "preview": "astro preview",
10
- "deploy": "astro build && wrangler deploy",
11
- "deploy:dev": "astro build && node scripts/build-dev-wrangler.mjs && wrangler deploy --config dist/server/wrangler.dev.json",
10
+ "deploy": "vitops email check && astro build && emdash migrate --wrangler-config wrangler.jsonc && wrangler deploy",
11
+ "deploy:dev": "vitops email check && astro build && node scripts/build-dev-wrangler.mjs && emdash migrate --wrangler-config dist/server/wrangler.dev.json && wrangler deploy --config dist/server/wrangler.dev.json",
12
12
  "init:github": "vitops setup repo",
13
13
  "init:hosting": "vitops setup hosting",
14
14
  "setup": "vitops setup all",
@@ -20,19 +20,23 @@
20
20
  },
21
21
  "dependencies": {
22
22
  "@astrojs/cloudflare": "^14.0.0",
23
- "@astrojs/react": "^6.0.0",
24
- "@emdash-cms/cloudflare": "^0.31.0",
23
+ "@astrojs/react": "^7.1.2",
24
+ "@emdash-cms/cloudflare": "^1.4.0",
25
25
  "@getvitops/astro": "latest",
26
+ "@getvitops/core": "latest",
26
27
  "@getvitops/emdash": "latest",
27
- "astro": "^7.1.2",
28
- "emdash": "^0.31.0",
29
- "react": "^19.2.4",
30
- "react-dom": "^19.2.4"
28
+ "@tailwindcss/vite": "^4.3.3",
29
+ "astro": "^7.4.4",
30
+ "emdash": "^1.4.0",
31
+ "react": "^19.3.1",
32
+ "react-dom": "^19.3.1",
33
+ "tailwindcss": "^4.3.3"
31
34
  },
32
35
  "devDependencies": {
33
- "@astrojs/check": "^0.9.7",
36
+ "@astrojs/check": "^0.9.12",
34
37
  "@cloudflare/workers-types": "^4.20260305.1",
35
38
  "@getvitops/cli": "latest",
39
+ "@iconify-json/fa7-solid": "^1.2.5",
36
40
  "typescript": "^6.0.3",
37
41
  "vite": "latest",
38
42
  "vite-plus": "latest",
@@ -41,11 +45,11 @@
41
45
  "devEngines": {
42
46
  "runtime": {
43
47
  "name": "node",
44
- "version": "24.18.0",
48
+ "version": "24",
45
49
  "onFail": "download"
46
50
  }
47
51
  },
48
- "packageManager": "pnpm@11.17.0",
52
+ "packageManager": "pnpm@12.16.1",
49
53
  "emdash": {
50
54
  "seed": "seed/seed.json"
51
55
  }
@@ -0,0 +1,183 @@
1
+ ---
2
+ lockfileVersion: '9.0'
3
+
4
+ importers:
5
+
6
+ .:
7
+ configDependencies: {}
8
+ packageManagerDependencies:
9
+ '@pnpm/exe':
10
+ specifier: 12.16.1
11
+ version: 12.16.1
12
+ pnpm:
13
+ specifier: 12.16.1
14
+ version: 12.16.1
15
+
16
+ packages:
17
+
18
+ '@pnpm/exe.android-arm64@12.16.1':
19
+ resolution: {integrity: sha512-PKf78Ew+i0CBYf0Xc+eMcqQiqyBT+u8XCVg1F5roc98/6wWfdYlWhrUMmEBiKWaJ3JqHxrtt8l1NwZ7qfJt2/Q==}
20
+ cpu: [arm64]
21
+ os: [android]
22
+
23
+ '@pnpm/exe.android-x64@12.16.1':
24
+ resolution: {integrity: sha512-xdu7gMbB98pdvhwMeA6612Of515FDlRUtfA/1f7nWPZfPLnEdSRBO2u+1N0XBtQ/ennhPH/lrxB1gC6gnR/cdg==}
25
+ cpu: [x64]
26
+ os: [android]
27
+
28
+ '@pnpm/exe.darwin-arm64@12.16.1':
29
+ resolution: {integrity: sha512-pVbmIIbhixiLvADLu1WA3TaW8FZy/D72R1De27WbbFx8/2mxvnsTyFVm4fO9kjpjMY7RzJd48CiQ96p8fO3ebQ==}
30
+ cpu: [arm64]
31
+ os: [darwin]
32
+
33
+ '@pnpm/exe.darwin-x64@12.16.1':
34
+ resolution: {integrity: sha512-xZvQBFqcZjO7vFKTK3XsJpqY6lnBL9EWSLCzVUPq3kZ94+D96gwJCa76xxGNK8Cj32f4eeM91Qg+yNRR4sRpDw==}
35
+ cpu: [x64]
36
+ os: [darwin]
37
+
38
+ '@pnpm/exe.freebsd-x64@12.16.1':
39
+ resolution: {integrity: sha512-zTtunfi9mBhRXiXEJYfwiJj0tk7MgTSfqDSRh+Az9FZ9THazVIiQiVNS8jpcsftDOqu7LKNffQdjmgwHDThfUg==}
40
+ cpu: [x64]
41
+ os: [freebsd]
42
+
43
+ '@pnpm/exe.linux-arm64-musl@12.16.1':
44
+ resolution: {integrity: sha512-BJ3mOmcmQgcUo92Ee/WfEOt1pRiv3y2MMAkhEiYHd85UiPpHTfFhv+SpCbALmfExzXk3UlaRtMYwHlkQymc4VA==}
45
+ cpu: [arm64]
46
+ os: [linux]
47
+ libc: [musl]
48
+
49
+ '@pnpm/exe.linux-arm64@12.16.1':
50
+ resolution: {integrity: sha512-JaRd5gNxwdNGBBkrZFt8bknrK4YmHVJBW0JMhUQ0fJ0dEYp6C2GT9ExaCqOO8EwYEyqM+jpKgJIK+8WFaJy3ew==}
51
+ cpu: [arm64]
52
+ os: [linux]
53
+ libc: [glibc]
54
+
55
+ '@pnpm/exe.linux-ppc64@12.16.1':
56
+ resolution: {integrity: sha512-FnSV0Jv40S1cMv7vFNWwvu0X567Lec4L4HCRead3CFcD6zQDNbGw81s8N5bcKPahtPD9ApVuhsbmFCx4rw6RMw==}
57
+ cpu: [ppc64]
58
+ os: [linux]
59
+ libc: [glibc]
60
+
61
+ '@pnpm/exe.linux-riscv64@12.16.1':
62
+ resolution: {integrity: sha512-C1Sww4FN5IttD4atRRhAKmQtSGWVp04ZAKNxO8pfu2bkRPwOW+7v+2DH1Xs1W+kZYYpO86BYDvUcadefF+AgaQ==}
63
+ cpu: [riscv64]
64
+ os: [linux]
65
+ libc: [glibc]
66
+
67
+ '@pnpm/exe.linux-s390x@12.16.1':
68
+ resolution: {integrity: sha512-kn2fautsTcxIMODoovQVqZyfpDRdNgGkoeVqNdrKqbeBBvrEl+fXLkmZiq5xDht1LMr4sYiCNcsMfNMT6JPFmg==}
69
+ cpu: [s390x]
70
+ os: [linux]
71
+ libc: [glibc]
72
+
73
+ '@pnpm/exe.linux-x64-musl@12.16.1':
74
+ resolution: {integrity: sha512-PM6ccHCOe/O9SsTflTJTYWfwogJZa6EmUvpnwZgiPguJBddh20wDQKgxUPXf48rDsPm9vMsIij0uHswwwbXL8g==}
75
+ cpu: [x64]
76
+ os: [linux]
77
+ libc: [musl]
78
+
79
+ '@pnpm/exe.linux-x64@12.16.1':
80
+ resolution: {integrity: sha512-RK//8ZLcXGW8A2k8bQOXZDBN1Qu92zN4dYnG1bzj1zoQ1fkZ6jNzZ1AvXtsfGVma795CJtvoaF5bLXf4l/FIUw==}
81
+ cpu: [x64]
82
+ os: [linux]
83
+ libc: [glibc]
84
+
85
+ '@pnpm/exe.win32-arm64@12.16.1':
86
+ resolution: {integrity: sha512-Ox3kNNVxtGw6pK7SVejmeOUgHhUTZgAM7NQQ6cU7frPw3ix9+j7d2MGbRg3fyEFAaKWq8ZAZLTQGcDyLnAu+qA==}
87
+ cpu: [arm64]
88
+ os: [win32]
89
+
90
+ '@pnpm/exe.win32-x64@12.16.1':
91
+ resolution: {integrity: sha512-k+FhRJ0ttphFoFIVB1Sk4v76YJAulafmA/Ly57cysesUhhIzVlApeOShUz0jXubKx317TThlEfpQrukldnqORA==}
92
+ cpu: [x64]
93
+ os: [win32]
94
+
95
+ '@pnpm/exe@12.16.1':
96
+ resolution: {integrity: sha512-Opsh2R7IuFY3ekd0C282Tmzgr5hiSlKMOv05/3dJXUrrp5NbmjC1Cm5PCFsa8xsiXY7z4oSkI4Qof1LjTkgAJg==}
97
+ engines: {node: '>=18'}
98
+ hasBin: true
99
+
100
+ pnpm@12.16.1:
101
+ resolution: {integrity: sha512-CR0d7nknV1Zhsl2rPCrjHK/BxU1rce1qZgDPDByxBDSkR+rhQBXxsj4ua+3u1535SpMuIWTSgyKA3OP7MvZW0Q==}
102
+ engines: {node: '>=18'}
103
+ hasBin: true
104
+
105
+ snapshots:
106
+
107
+ '@pnpm/exe.android-arm64@12.16.1':
108
+ optional: true
109
+
110
+ '@pnpm/exe.android-x64@12.16.1':
111
+ optional: true
112
+
113
+ '@pnpm/exe.darwin-arm64@12.16.1':
114
+ optional: true
115
+
116
+ '@pnpm/exe.darwin-x64@12.16.1':
117
+ optional: true
118
+
119
+ '@pnpm/exe.freebsd-x64@12.16.1':
120
+ optional: true
121
+
122
+ '@pnpm/exe.linux-arm64-musl@12.16.1':
123
+ optional: true
124
+
125
+ '@pnpm/exe.linux-arm64@12.16.1':
126
+ optional: true
127
+
128
+ '@pnpm/exe.linux-ppc64@12.16.1':
129
+ optional: true
130
+
131
+ '@pnpm/exe.linux-riscv64@12.16.1':
132
+ optional: true
133
+
134
+ '@pnpm/exe.linux-s390x@12.16.1':
135
+ optional: true
136
+
137
+ '@pnpm/exe.linux-x64-musl@12.16.1':
138
+ optional: true
139
+
140
+ '@pnpm/exe.linux-x64@12.16.1':
141
+ optional: true
142
+
143
+ '@pnpm/exe.win32-arm64@12.16.1':
144
+ optional: true
145
+
146
+ '@pnpm/exe.win32-x64@12.16.1':
147
+ optional: true
148
+
149
+ '@pnpm/exe@12.16.1':
150
+ optionalDependencies:
151
+ '@pnpm/exe.android-arm64': 12.16.1
152
+ '@pnpm/exe.android-x64': 12.16.1
153
+ '@pnpm/exe.darwin-arm64': 12.16.1
154
+ '@pnpm/exe.darwin-x64': 12.16.1
155
+ '@pnpm/exe.freebsd-x64': 12.16.1
156
+ '@pnpm/exe.linux-arm64': 12.16.1
157
+ '@pnpm/exe.linux-arm64-musl': 12.16.1
158
+ '@pnpm/exe.linux-ppc64': 12.16.1
159
+ '@pnpm/exe.linux-riscv64': 12.16.1
160
+ '@pnpm/exe.linux-s390x': 12.16.1
161
+ '@pnpm/exe.linux-x64': 12.16.1
162
+ '@pnpm/exe.linux-x64-musl': 12.16.1
163
+ '@pnpm/exe.win32-arm64': 12.16.1
164
+ '@pnpm/exe.win32-x64': 12.16.1
165
+
166
+ pnpm@12.16.1:
167
+ optionalDependencies:
168
+ '@pnpm/exe.android-arm64': 12.16.1
169
+ '@pnpm/exe.android-x64': 12.16.1
170
+ '@pnpm/exe.darwin-arm64': 12.16.1
171
+ '@pnpm/exe.darwin-x64': 12.16.1
172
+ '@pnpm/exe.freebsd-x64': 12.16.1
173
+ '@pnpm/exe.linux-arm64': 12.16.1
174
+ '@pnpm/exe.linux-arm64-musl': 12.16.1
175
+ '@pnpm/exe.linux-ppc64': 12.16.1
176
+ '@pnpm/exe.linux-riscv64': 12.16.1
177
+ '@pnpm/exe.linux-s390x': 12.16.1
178
+ '@pnpm/exe.linux-x64': 12.16.1
179
+ '@pnpm/exe.linux-x64-musl': 12.16.1
180
+ '@pnpm/exe.win32-arm64': 12.16.1
181
+ '@pnpm/exe.win32-x64': 12.16.1
182
+
183
+ ---
@@ -8,7 +8,7 @@ allowBuilds:
8
8
 
9
9
  # Supply-chain hardening: cooldown on brand-new releases (toolchain exempt)
10
10
  # and no non-registry transitive sources.
11
- minimumReleaseAge: 1440
11
+ minimumReleaseAge: 4320
12
12
  minimumReleaseAgeExclude:
13
13
  - '@getvitops/*'
14
14
  - emdash
@@ -0,0 +1,10 @@
1
+ # Cloudflare Workers static assets apply this file to every asset response.
2
+ #
3
+ # A baseline that cannot break a page. No Content-Security-Policy on purpose: <Head /> emits
4
+ # inline scripts (the consent stub, the colour-scheme bootstrap), so a strict policy needs
5
+ # per-site nonces or hashes — add one deliberately once you know which third-party tags you load.
6
+ /*
7
+ X-Content-Type-Options: nosniff
8
+ Referrer-Policy: strict-origin-when-cross-origin
9
+ Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()
10
+ X-Frame-Options: SAMEORIGIN
@@ -66,6 +66,12 @@ cfg.r2_buckets = (cfg.r2_buckets ?? []).map((r) =>
66
66
  r.binding === 'MEDIA' ? { ...r, bucket_name: `${r.bucket_name}-dev` } : r,
67
67
  );
68
68
 
69
+ // No cron on dev. Dev's database is a copy of prod (scripts/refresh-dev.mjs),
70
+ // so it carries prod's scheduled publishes and plugin jobs; leaving the trigger
71
+ // on would run them a second time against the copy. The cost: scheduled
72
+ // publishing can't be exercised on dev.
73
+ delete cfg.triggers;
74
+
69
75
  // Flat config — no nested environments.
70
76
  delete cfg.env;
71
77