@getvitops/create 0.4.0 → 0.6.0

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 (48) hide show
  1. package/CHANGELOG.md +129 -5
  2. package/README.md +7 -0
  3. package/package.json +17 -2
  4. package/templates/emdash/.env +1 -0
  5. package/templates/emdash/.github/workflows/ci.yml +12 -0
  6. package/templates/emdash/.github/workflows/deploy-dev.yml +17 -19
  7. package/templates/emdash/.github/workflows/deploy-prod.yml +17 -21
  8. package/templates/emdash/.github/workflows/promote.yml +8 -36
  9. package/templates/emdash/.mcp.json +4 -0
  10. package/templates/emdash/.nvmrc +1 -0
  11. package/templates/emdash/AGENTS.md +47 -0
  12. package/templates/emdash/README.md +4 -0
  13. package/templates/emdash/design-system.json +2 -2
  14. package/templates/emdash/package.json +1 -0
  15. package/templates/emdash/scripts/init-github.mjs +94 -10
  16. package/templates/emdash/src/assets/placeholder/wireframe-400x400.png +0 -0
  17. package/templates/emdash/src/assets/placeholder/wireframe-400x400.svg +1 -0
  18. package/templates/emdash/src/assets/placeholder/wireframe-400x600.png +0 -0
  19. package/templates/emdash/src/assets/placeholder/wireframe-400x600.svg +1 -0
  20. package/templates/emdash/src/assets/placeholder/wireframe-600x400.png +0 -0
  21. package/templates/emdash/src/assets/placeholder/wireframe-600x400.svg +1 -0
  22. package/templates/emdash/vite.config.ts +6 -0
  23. package/templates/static/.env +1 -0
  24. package/templates/static/.github/workflows/ci.yml +12 -0
  25. package/templates/static/.github/workflows/deploy-dev.yml +33 -0
  26. package/templates/static/.github/workflows/deploy-prod.yml +29 -0
  27. package/templates/static/.github/workflows/promote.yml +16 -0
  28. package/templates/static/.nvmrc +1 -0
  29. package/templates/static/AGENTS.md +57 -0
  30. package/templates/static/README.md +85 -0
  31. package/templates/static/_gitignore +24 -0
  32. package/templates/static/astro.config.mjs +19 -0
  33. package/templates/static/design-system.json +148 -0
  34. package/templates/static/package.json +39 -0
  35. package/templates/static/scripts/dev-wrangler-config.mjs +28 -0
  36. package/templates/static/scripts/init-github.mjs +186 -0
  37. package/templates/static/scripts/init-hosting.mjs +62 -0
  38. package/templates/static/src/assets/placeholder/wireframe-400x400.png +0 -0
  39. package/templates/static/src/assets/placeholder/wireframe-400x400.svg +1 -0
  40. package/templates/static/src/assets/placeholder/wireframe-400x600.png +0 -0
  41. package/templates/static/src/assets/placeholder/wireframe-400x600.svg +1 -0
  42. package/templates/static/src/assets/placeholder/wireframe-600x400.png +0 -0
  43. package/templates/static/src/assets/placeholder/wireframe-600x400.svg +1 -0
  44. package/templates/static/src/layouts/Layout.astro +26 -0
  45. package/templates/static/src/pages/404.astro +11 -0
  46. package/templates/static/src/pages/index.astro +13 -0
  47. package/templates/static/tsconfig.json +5 -0
  48. package/templates/static/wrangler.jsonc +15 -0
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="400" height="600" viewBox="0 0 400 600"><rect width="100%" height="100%" fill="#DDDDDD"/><path fill="#999999" d="M87.3 304.72h11.66v-12.54q0-1.77.24-3.92zm17.36 0h4.82v3.79q0 .53-.35.91-.34.39-.98.39h-3.49v9.35h-5.7v-9.35H82.79q-.66 0-1.16-.42-.51-.41-.64-1.02l-.69-3.31 18.16-24.25h6.2zm35.59-4.72q0 5.01-1.08 8.71-1.07 3.69-2.97 6.1-1.89 2.42-4.47 3.59-2.59 1.18-5.58 1.18-3 0-5.55-1.18-2.56-1.17-4.44-3.59-1.88-2.41-2.94-6.1-1.06-3.7-1.06-8.71 0-5.03 1.06-8.72 1.06-3.68 2.94-6.09t4.44-3.59q2.55-1.18 5.55-1.18 2.99 0 5.58 1.18 2.58 1.18 4.47 3.59 1.9 2.41 2.97 6.09 1.08 3.69 1.08 8.72m-6.76 0q0-4.16-.61-6.89t-1.63-4.35q-1.02-1.61-2.35-2.26-1.32-.65-2.75-.65-1.41 0-2.72.65t-2.32 2.26q-1 1.62-1.6 4.35t-.6 6.89.6 6.89 1.6 4.35q1.01 1.61 2.32 2.26t2.72.65q1.43 0 2.75-.65 1.33-.65 2.35-2.26 1.02-1.62 1.63-4.35t.61-6.89m37.5 0q0 5.01-1.08 8.71-1.07 3.69-2.97 6.1-1.89 2.42-4.47 3.59-2.59 1.18-5.58 1.18-3 0-5.55-1.18-2.56-1.17-4.44-3.59-1.88-2.41-2.94-6.1-1.06-3.7-1.06-8.71 0-5.03 1.06-8.72 1.06-3.68 2.94-6.09t4.44-3.59q2.55-1.18 5.55-1.18 2.99 0 5.58 1.18 2.58 1.18 4.47 3.59 1.9 2.41 2.97 6.09 1.08 3.69 1.08 8.72m-6.76 0q0-4.16-.61-6.89t-1.63-4.35q-1.02-1.61-2.35-2.26-1.32-.65-2.75-.65-1.41 0-2.72.65t-2.32 2.26q-1 1.62-1.6 4.35t-.6 6.89.6 6.89 1.6 4.35q1.01 1.61 2.32 2.26t2.72.65q1.43 0 2.75-.65 1.33-.65 2.35-2.26 1.02-1.62 1.63-4.35t.61-6.89m48.84 10.39-3.47 3.42-8.99-8.99-9.06 9.04-3.47-3.42 9.06-9.09-8.64-8.64 3.45-3.44 8.64 8.64 8.58-8.59 3.5 3.45-8.61 8.61zm40.94-29.55-11.37 13.91-1.32 1.65q1.11-.56 2.4-.86 1.28-.31 2.76-.31 2.18 0 4.23.72 2.05.71 3.62 2.16 1.56 1.44 2.52 3.59.95 2.14.95 5 0 2.68-.98 5.03-.98 2.34-2.76 4.09-1.77 1.75-4.28 2.76-2.5 1-5.52 1-3.08 0-5.51-.98-2.44-.98-4.16-2.74-1.73-1.76-2.64-4.24-.92-2.48-.92-5.5 0-2.7 1.1-5.55t3.41-5.92l9.14-12.27q.48-.64 1.39-1.09.92-.45 2.11-.45zm-9.88 33.39q1.56 0 2.87-.53t2.25-1.48q.94-.96 1.47-2.24.53-1.29.53-2.8 0-1.64-.5-2.95t-1.43-2.23q-.93-.91-2.23-1.39-1.29-.48-2.86-.48-1.56 0-2.83.53-1.28.53-2.18 1.47t-1.4 2.23-.5 2.77q0 1.59.43 2.9.44 1.31 1.3 2.24t2.13 1.44q1.28.52 2.95.52M288.96 300q0 5.01-1.07 8.71-1.07 3.69-2.97 6.1-1.89 2.42-4.48 3.59-2.58 1.18-5.57 1.18-3 0-5.56-1.18-2.55-1.17-4.43-3.59-1.89-2.41-2.95-6.1-1.06-3.7-1.06-8.71 0-5.03 1.06-8.72 1.06-3.68 2.95-6.09 1.88-2.41 4.43-3.59 2.56-1.18 5.56-1.18 2.99 0 5.57 1.18 2.59 1.18 4.48 3.59 1.9 2.41 2.97 6.09 1.07 3.69 1.07 8.72m-6.75 0q0-4.16-.61-6.89t-1.63-4.35q-1.02-1.61-2.35-2.26-1.32-.65-2.75-.65-1.41 0-2.72.65t-2.32 2.26q-1.01 1.62-1.6 4.35-.6 2.73-.6 6.89t.6 6.89q.59 2.73 1.6 4.35 1.01 1.61 2.32 2.26t2.72.65q1.43 0 2.75-.65 1.33-.65 2.35-2.26 1.02-1.62 1.63-4.35t.61-6.89m37.49 0q0 5.01-1.07 8.71-1.07 3.69-2.97 6.1-1.89 2.42-4.48 3.59-2.58 1.18-5.57 1.18-3 0-5.56-1.18-2.55-1.17-4.43-3.59-1.89-2.41-2.95-6.1-1.06-3.7-1.06-8.71 0-5.03 1.06-8.72 1.06-3.68 2.95-6.09 1.88-2.41 4.43-3.59 2.56-1.18 5.56-1.18 2.99 0 5.57 1.18 2.59 1.18 4.48 3.59 1.9 2.41 2.97 6.09 1.07 3.69 1.07 8.72m-6.75 0q0-4.16-.61-6.89t-1.63-4.35q-1.02-1.61-2.35-2.26-1.32-.65-2.75-.65-1.41 0-2.72.65t-2.32 2.26q-1.01 1.62-1.6 4.35-.6 2.73-.6 6.89t.6 6.89q.59 2.73 1.6 4.35 1.01 1.61 2.32 2.26t2.72.65q1.43 0 2.75-.65 1.33-.65 2.35-2.26 1.02-1.62 1.63-4.35t.61-6.89"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="600" height="400" viewBox="0 0 600 400"><rect width="100%" height="100%" fill="#DDDDDD"/><path fill="#999999" d="m155.52 171.08-17.16 21-2 2.48q1.68-.84 3.62-1.3t4.18-.46q3.28 0 6.38 1.08t5.46 3.26 3.8 5.42 1.44 7.56q0 4.04-1.48 7.58t-4.16 6.18-6.46 4.16-8.34 1.52q-4.64 0-8.32-1.48t-6.28-4.14-3.98-6.4-1.38-8.3q0-4.08 1.66-8.38t5.14-8.94l13.8-18.52q.72-.96 2.1-1.64t3.18-.68zm-14.92 50.4q2.36 0 4.34-.8t3.4-2.24 2.22-3.38.8-4.22q0-2.48-.76-4.46t-2.16-3.36-3.36-2.1-4.32-.72-4.28.8-3.28 2.22-2.12 3.36-.76 4.18q0 2.4.66 4.38t1.96 3.38 3.22 2.18 4.44.78M208.28 200q0 7.56-1.62 13.14t-4.48 9.22-6.76 5.42-8.42 1.78-8.38-1.78-6.7-5.42-4.44-9.22-1.6-13.14q0-7.6 1.6-13.16t4.44-9.2 6.7-5.42 8.38-1.78 8.42 1.78 6.76 5.42 4.48 9.2 1.62 13.16m-10.2 0q0-6.28-.92-10.4t-2.46-6.56-3.54-3.42-4.16-.98q-2.12 0-4.1.98t-3.5 3.42-2.42 6.56-.9 10.4.9 10.4 2.42 6.56 3.5 3.42 4.1.98q2.16 0 4.16-.98t3.54-3.42 2.46-6.56.92-10.4m56.6 0q0 7.56-1.62 13.14t-4.48 9.22-6.76 5.42-8.42 1.78-8.38-1.78-6.7-5.42-4.44-9.22-1.6-13.14q0-7.6 1.6-13.16t4.44-9.2 6.7-5.42 8.38-1.78 8.42 1.78 6.76 5.42 4.48 9.2 1.62 13.16m-10.2 0q0-6.28-.92-10.4t-2.46-6.56-3.54-3.42-4.16-.98q-2.12 0-4.1.98t-3.5 3.42-2.42 6.56-.9 10.4.9 10.4 2.42 6.56 3.5 3.42 4.1.98q2.16 0 4.16-.98t3.54-3.42 2.46-6.56.92-10.4m73.72 15.68-5.24 5.16-13.56-13.56-13.68 13.64-5.24-5.16 13.68-13.72L281.12 189l5.2-5.2 13.04 13.04 12.96-12.96 5.28 5.2-13 13zm34.64-8.56h17.6V188.2q0-2.68.36-5.92zm26.2 0h7.28v5.72q0 .8-.52 1.38t-1.48.58h-5.28v14.12h-8.6V214.8h-24.4q-1 0-1.76-.62t-.96-1.54l-1.04-5 27.4-36.6h9.36zm53.72-7.12q0 7.56-1.62 13.14t-4.48 9.22-6.76 5.42-8.42 1.78-8.38-1.78-6.7-5.42-4.44-9.22-1.6-13.14q0-7.6 1.6-13.16t4.44-9.2 6.7-5.42 8.38-1.78 8.42 1.78 6.76 5.42 4.48 9.2 1.62 13.16m-10.2 0q0-6.28-.92-10.4t-2.46-6.56-3.54-3.42-4.16-.98q-2.12 0-4.1.98t-3.5 3.42-2.42 6.56-.9 10.4.9 10.4 2.42 6.56 3.5 3.42 4.1.98q2.16 0 4.16-.98t3.54-3.42 2.46-6.56.92-10.4m56.6 0q0 7.56-1.62 13.14t-4.48 9.22-6.76 5.42-8.42 1.78-8.38-1.78-6.7-5.42-4.44-9.22-1.6-13.14q0-7.6 1.6-13.16t4.44-9.2 6.7-5.42 8.38-1.78 8.42 1.78 6.76 5.42 4.48 9.2 1.62 13.16m-10.2 0q0-6.28-.92-10.4t-2.46-6.56-3.54-3.42-4.16-.98q-2.12 0-4.1.98t-3.5 3.42-2.42 6.56-.9 10.4.9 10.4 2.42 6.56 3.5 3.42 4.1.98q2.16 0 4.16-.98t3.54-3.42 2.46-6.56.92-10.4"/></svg>
@@ -3,6 +3,12 @@ import { defineConfig } from 'vite-plus';
3
3
  export default defineConfig({
4
4
  staged: {
5
5
  '*': 'vp check --fix',
6
+ // Design-system drift, checked on the files being committed. `--strict` makes
7
+ // the reuse hints fail here: a hand-rolled container or a card set without
8
+ // `subgrid` is the drift this catches, and it is only ever cheap to fix at the
9
+ // moment it is written. `vitops lint` takes the staged paths as positionals.
10
+ 'src/**/*.{astro,html,ts,tsx,jsx,vue,svelte,css}':
11
+ 'vitops lint -i design-system.json -f tailwind --strict',
6
12
  },
7
13
  fmt: {
8
14
  ignorePatterns: ['dist/**', 'node_modules/**', 'src/styles/**', 'public/vitops/**'],
@@ -0,0 +1 @@
1
+ CLOUDFLARE_API_TOKEN=your_cloudflare_api_token
@@ -0,0 +1,12 @@
1
+ # Runs on every PR: typecheck + design-lint + build. deploy-dev.yml /
2
+ # deploy-prod.yml call the same reusable `site-ci.yml` themselves before they
3
+ # deploy, so this is what gives a PR the identical signal before it's even
4
+ # merged to `dev` — a broken build never reaches the dev worker.
5
+ name: CI
6
+
7
+ on:
8
+ pull_request:
9
+
10
+ jobs:
11
+ ci:
12
+ uses: getvitops/design-system/.github/workflows/site-ci.yml@v1
@@ -0,0 +1,33 @@
1
+ # Deploys the `dev` branch to the isolated dev worker (<name>-dev, and
2
+ # dev.<domain> if a custom domain is configured in wrangler.jsonc).
3
+ # `dev` is the integration branch — every push here refreshes the review site.
4
+ # Promote to production with the "Promote dev → main" workflow (promote.yml).
5
+ #
6
+ # Deploys via the vitops toolchain's reusable static-site deploy workflow — see
7
+ # https://github.com/getvitops/design-system/blob/main/.github/workflows/site-deploy-static.yml
8
+ # Pinned to @v1 so a fix there reaches this repo without a manual re-paste;
9
+ # bump the tag deliberately if you want to pick up a change.
10
+ #
11
+ # Required repo secrets:
12
+ # CLOUDFLARE_API_TOKEN — token with Workers edit on this account
13
+ # CLOUDFLARE_ACCOUNT_ID — the Cloudflare account id
14
+ name: Deploy dev
15
+
16
+ on:
17
+ push:
18
+ branches: [dev]
19
+
20
+ concurrency:
21
+ group: deploy-dev
22
+ cancel-in-progress: true
23
+
24
+ jobs:
25
+ deploy:
26
+ uses: getvitops/design-system/.github/workflows/site-deploy-static.yml@v1
27
+ with:
28
+ environment: dev
29
+ worker-name-suffix: -dev
30
+ route-prefix: dev.
31
+ secrets:
32
+ CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
33
+ CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
@@ -0,0 +1,29 @@
1
+ # Deploys `main` to production.
2
+ # `main` should be branch-protected — it then only advances via the Promote
3
+ # workflow (promote.yml), so a push here always represents promoted code. The
4
+ # `production` GitHub Environment (set up by `scripts/init-github.mjs`) has
5
+ # required reviewers restricted to admins, so this PAUSES for approval before
6
+ # deploying.
7
+ #
8
+ # Deploys via the vitops toolchain's reusable static-site deploy workflow — see
9
+ # https://github.com/getvitops/design-system/blob/main/.github/workflows/site-deploy-static.yml
10
+ #
11
+ # Required repo secrets: CLOUDFLARE_API_TOKEN, CLOUDFLARE_ACCOUNT_ID
12
+ name: Deploy prod
13
+
14
+ on:
15
+ push:
16
+ branches: [main]
17
+
18
+ concurrency:
19
+ group: deploy-prod
20
+ cancel-in-progress: false
21
+
22
+ jobs:
23
+ deploy:
24
+ uses: getvitops/design-system/.github/workflows/site-deploy-static.yml@v1
25
+ with:
26
+ environment: production
27
+ secrets:
28
+ CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
29
+ CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
@@ -0,0 +1,16 @@
1
+ # Promote dev → main. Run manually after reviewing the dev site.
2
+ # Opens a PR from dev into the protected `main` branch and enables auto-merge;
3
+ # the merge triggers Deploy prod.
4
+ #
5
+ # Deploys via the vitops toolchain's reusable promote workflow — see
6
+ # https://github.com/getvitops/design-system/blob/main/.github/workflows/site-promote.yml
7
+ # for the branch-protection / PROMOTE_TOKEN options.
8
+ name: Promote dev → main
9
+
10
+ on:
11
+ workflow_dispatch:
12
+
13
+ jobs:
14
+ promote:
15
+ uses: getvitops/design-system/.github/workflows/site-promote.yml@v1
16
+ secrets: inherit
@@ -0,0 +1 @@
1
+ 24
@@ -0,0 +1,57 @@
1
+ This is a static Astro website styled by the Vitops design system, deployed
2
+ as Cloudflare Workers static assets (no server runtime, no database).
3
+
4
+ ## Ground rules
5
+
6
+ - `design-system.json` is the single source of truth for the design system
7
+ (colors, type, spacing, patterns, animations). Never edit `src/styles/` by
8
+ hand — it is generated from the JSON by the `vitops()` integration on every
9
+ dev/build and is gitignored.
10
+ - `src/assets/placeholder/` holds neutral wireframe stand-ins (square,
11
+ portrait, landscape; SVG + PNG) for layout work before real imagery
12
+ exists. Delete the directory once real assets land.
13
+ - Prefer framework CSS classes (utilities, patterns, type roles like
14
+ `font-heading`) over bespoke CSS. Run `npx vitops agents` to append the
15
+ full generated class-vocabulary reference to this file.
16
+ - **Layout foundations — these are the answer, not a starting point.** Six
17
+ substitutions carry the structure of nearly every page:
18
+ | About to write… | Write instead |
19
+ | --- | --- |
20
+ | a `wrap`/`wrapper`/`container`/`inner` class | **`centered`** |
21
+ | `max-width` + `margin-inline: auto` | **`centered`** |
22
+ | `padding-block` on a section | **`region`** |
23
+ | margins between headings/paragraphs/lists | **`rhythm`** |
24
+ | `display: grid` + `grid-template-columns: repeat(n, …)` | **`subgrid`** |
25
+ | `repeat(auto-fit, minmax(…))` | **`grid-auto`** |
26
+ | `display: flex` + `gap` for a row of controls | **`cluster`** |
27
+ - Every page is prerendered by default (`output: 'static'`) — there is no
28
+ server to fall back to, so nothing here can read request-time data
29
+ (cookies, headers, query params) at render time. If a page genuinely needs
30
+ that, it needs an adapter and a different template — this one stays pure
31
+ static on purpose.
32
+
33
+ ## Branch model
34
+
35
+ - Work on **`dev`** (the integration branch). Every push auto-deploys the
36
+ isolated `-dev` worker (`dev.<domain>` with a custom domain).
37
+ - **`main`** is production and branch-protected — never push or merge to it
38
+ directly. Production ships only via the manual **promote** flow:
39
+ `.github/workflows/promote.yml`, dispatched manually, opens a `dev → main`
40
+ PR with auto-merge; merging deploys prod. Only run it when the user
41
+ explicitly asks to promote/ship to production.
42
+
43
+ ## Commands
44
+
45
+ - `pnpm dev` — local dev
46
+ - `pnpm typecheck` — `astro check`
47
+ - `pnpm run build:css` — regenerate the framework CSS from `design-system.json`
48
+ - `pnpm deploy` — build + `wrangler deploy` to prod
49
+ - `pnpm run deploy:dev` — build + deploy the isolated dev worker
50
+ - `pnpm run init:github` — one-time: create + push the GitHub repo (main +
51
+ dev, dev default, branch protection + environment policy). Only run when
52
+ the user asks to set up GitHub.
53
+ - `pnpm run init:hosting` — one-time: read the Cloudflare account id and set
54
+ it as a repo secret. Only run when the user asks for it.
55
+ - `npx vitops validate design-system.json` — schema-check the design config
56
+ - `npx vitops lint -i design-system.json -f css` — find framework classes in
57
+ source that resolve to nothing under this format
@@ -0,0 +1,85 @@
1
+ # My Static Site
2
+
3
+ A static [Astro](https://astro.build) website on Cloudflare Workers (static
4
+ assets — no server runtime), styled by the
5
+ [Vitops design system](https://www.npmjs.com/org/getvitops).
6
+
7
+ Scaffolded from `vp create @getvitops:static`.
8
+
9
+ ## Stack
10
+
11
+ - **Astro** (`output: 'static'`) on **Cloudflare Workers Static Assets** — no
12
+ adapter, no database, no server runtime
13
+ - **`@getvitops/astro`** — generates the design-system CSS from
14
+ `design-system.json` and serves the web-component runtime
15
+
16
+ `src/assets/placeholder/` ships neutral wireframe images for layout work
17
+ before real imagery exists — delete once real assets land.
18
+
19
+ ## Local development
20
+
21
+ ```bash
22
+ pnpm install
23
+ pnpm dev
24
+ ```
25
+
26
+ - Site: <http://localhost:4321>
27
+
28
+ ## Deploy
29
+
30
+ ```bash
31
+ npx wrangler login
32
+ pnpm deploy
33
+ ```
34
+
35
+ For a custom domain, uncomment the `routes` block in `wrangler.jsonc` and set
36
+ your apex — Cloudflare provisions the DNS record + TLS cert on deploy.
37
+
38
+ ## Environments: dev → main promotion
39
+
40
+ The repo ships a two-environment flow modeled on branch = environment:
41
+
42
+ - **`dev`** is the integration branch. Every push auto-deploys the isolated
43
+ `-dev` worker (`.github/workflows/deploy-dev.yml`), served at
44
+ `dev.<domain>` when a custom domain is configured (or the worker's
45
+ `workers.dev` URL otherwise).
46
+ - **`main`** is production. Every push auto-deploys the prod worker
47
+ (`.github/workflows/deploy-prod.yml`) — gated behind a `production`
48
+ GitHub Environment that requires an admin's approval before it runs.
49
+ - **Promotion is manual**: run the **"Promote dev → main"** workflow
50
+ (`.github/workflows/promote.yml`) and it opens a PR from `dev` into `main`
51
+ with auto-merge enabled. With required reviews on `main`, a human approves
52
+ the PR; merging deploys prod (after the admin approval above).
53
+
54
+ One-time setup:
55
+
56
+ 1. `pnpm run init:github` — creates a GitHub repo named after this project
57
+ (via the `gh` CLI; `-- --public` for a public repo), commits if needed,
58
+ pushes `main` + `dev`, makes `dev` the default branch, protects `main`
59
+ (PR + review + the `ci` check required), and creates a `production`
60
+ environment gated on your admin collaborators. Idempotent; `-- --dry-run`
61
+ previews. (Branch protection and environment reviewers need GitHub
62
+ Pro/Team on a private repo — the script prints the manual equivalent if
63
+ your plan doesn't support them.)
64
+ 2. `pnpm run init:hosting` — reads your Cloudflare account id (after
65
+ `npx wrangler login`) and sets the `CLOUDFLARE_ACCOUNT_ID` repo secret.
66
+ Idempotent; `-- --dry-run` previews.
67
+ 3. Create a Cloudflare API token (Workers edit —
68
+ <https://dash.cloudflare.com/profile/api-tokens>; tokens can't be created
69
+ via CLI) and `gh secret set CLOUDFLARE_API_TOKEN`. Optionally
70
+ `PROMOTE_TOKEN` (a PAT allowed to bypass protection) for hands-off
71
+ promotion. The first workflow runs fail until the secrets exist.
72
+
73
+ `pnpm run deploy:dev` reproduces the dev deploy locally: it writes a
74
+ gitignored `.wrangler.dev.json` with the worker renamed and any custom-domain
75
+ route prefixed `dev.` (`scripts/dev-wrangler-config.mjs`), so it never
76
+ touches the prod worker.
77
+
78
+ ## CI/deploy workflows
79
+
80
+ `.github/workflows/{ci,deploy-dev,deploy-prod,promote}.yml` are thin callers
81
+ of reusable workflows published by
82
+ [`getvitops/design-system`](https://github.com/getvitops/design-system),
83
+ pinned to `@v1`. A fix to the shared deploy logic there reaches this repo the
84
+ next time those workflows run — no re-pasting needed. Bump the pin
85
+ deliberately if you want to hold back a change.
@@ -0,0 +1,24 @@
1
+ # build output
2
+ dist/
3
+
4
+ # dependencies
5
+ node_modules/
6
+
7
+ # generated types
8
+ .astro/
9
+
10
+ # wrangler local state
11
+ .wrangler/
12
+ .wrangler.dev.json
13
+
14
+ # generated by the vitops() integration on dev/build
15
+ src/styles/
16
+ public/vitops/
17
+
18
+ # environment
19
+ .env
20
+ .env.*
21
+ !.env.example
22
+
23
+ # os / editor
24
+ .DS_Store
@@ -0,0 +1,19 @@
1
+ // @ts-check
2
+ import vitops from '@getvitops/astro';
3
+ import { defineConfig } from 'astro/config';
4
+
5
+ export default defineConfig({
6
+ // Pure static output — deploys as Workers Static Assets (see
7
+ // wrangler.jsonc), no adapter and no server runtime.
8
+ output: 'static',
9
+ integrations: [
10
+ vitops({
11
+ css: {
12
+ input: 'design-system.json',
13
+ format: 'css',
14
+ out: 'src/styles',
15
+ },
16
+ webComponents: true,
17
+ }),
18
+ ],
19
+ });
@@ -0,0 +1,148 @@
1
+ {
2
+ "$schema": "./node_modules/@getvitops/generator/schema.json",
3
+ "colors": {
4
+ "palette": {
5
+ "brand": { "seed": "#2e9b73" },
6
+ "ink": { "seed": "#3f4a5c" },
7
+ "sky": { "seed": "#2f7bc0" },
8
+ "sun": { "seed": "#d08a1f" },
9
+ "rose": { "seed": "#c74a42" }
10
+ },
11
+ "roles": {
12
+ "neutral": "ink",
13
+ "surface": "ink",
14
+ "ui-primary": "brand",
15
+ "brand-primary": "brand",
16
+ "info": "sky",
17
+ "success": "brand",
18
+ "warning": "sun",
19
+ "danger": "rose"
20
+ },
21
+ "utilities": ["bg", "text", "icon", "border"]
22
+ },
23
+ "shadows": {
24
+ "sm": "0 1px 2px rgb(0 0 0 / 0.08)",
25
+ "md": "0 4px 6px rgb(0 0 0 / 0.12)",
26
+ "lg": "0 10px 15px rgb(0 0 0 / 0.18)"
27
+ },
28
+ "fonts": {
29
+ "display": "system-ui, -apple-system, \"Segoe UI\", sans-serif",
30
+ "sans": "system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif",
31
+ "mono": "ui-monospace, \"SF Mono\", Menlo, monospace"
32
+ },
33
+ "typeScale": {
34
+ "base": "1rem",
35
+ "names": ["2xs", "xs", "s", "m", "l", "xl", "2xl", "3xl"],
36
+ "baseStep": 4,
37
+ "baseline": "m",
38
+ "ratio": 1.2,
39
+ "fluid": { "minVw": "22.5rem", "maxVw": "80rem", "minRatio": 1.12 }
40
+ },
41
+ "spaceScale": {
42
+ "base": "1rem",
43
+ "names": ["2xs", "xs", "s", "m", "l", "xl", "2xl", "3xl"],
44
+ "baseStep": 4,
45
+ "baseline": "m",
46
+ "ratio": 1.25,
47
+ "fluid": { "minVw": "22.5rem", "maxVw": "80rem", "minRatio": 1.2 }
48
+ },
49
+ "patterns": {
50
+ "defaults": {
51
+ "ds": "none",
52
+ "b": "1px solid var(--color-bg-surface-x-muted)",
53
+ "br": "0.375rem",
54
+ "p": "1rem",
55
+ "fs": "1rem"
56
+ },
57
+ "radii": { "circle": "50%" },
58
+ "groups": {
59
+ "control": {
60
+ "ds": "var(--ds-default)",
61
+ "b": "var(--b-default)",
62
+ "br": "var(--br-default)",
63
+ "p": "0.5em 1em",
64
+ "fs": "var(--fs-default)"
65
+ },
66
+ "panel": {
67
+ "ds": "var(--shadow-md)",
68
+ "b": "var(--b-default)",
69
+ "br": "0.5rem",
70
+ "p": "1rem",
71
+ "fs": "var(--fs-default)"
72
+ }
73
+ },
74
+ "z": { "raised": 1, "sticky": 100, "overlay": 200, "top": 1000 },
75
+ "items": {
76
+ "button": {
77
+ "group": "control",
78
+ "element": "button",
79
+ "default_role": "brand-primary",
80
+ "base": {
81
+ "padding": "0.6em 1.2em",
82
+ "border-radius": "var(--br-control, 0.25rem)",
83
+ "border": "none",
84
+ "font-weight": "600",
85
+ "color": "#fff",
86
+ "cursor": "pointer",
87
+ "box-shadow": "var(--shadow-sm)"
88
+ },
89
+ "states": {
90
+ "hover": { "step": 1 },
91
+ "active": { "scale": 0.97 },
92
+ "focus-visible": { "ring": true }
93
+ },
94
+ "roles": []
95
+ },
96
+ "card": {
97
+ "group": "panel",
98
+ "class": "card",
99
+ "base": {
100
+ "border-radius": "var(--br-card-group)",
101
+ "padding": "1.5rem",
102
+ "background": "var(--color-bg-surface-muted)",
103
+ "border": "var(--b-card-group)",
104
+ "box-shadow": "var(--ds-card-group)"
105
+ },
106
+ "states": {},
107
+ "roles": []
108
+ }
109
+ }
110
+ },
111
+ "typography": {
112
+ "families": {
113
+ "display": "var(--font-display)",
114
+ "sans": "var(--font-sans)",
115
+ "code": "var(--font-mono, ui-monospace, monospace)"
116
+ },
117
+ "roles": {
118
+ "display": {
119
+ "family": "display",
120
+ "size": "var(--text-3xl)",
121
+ "weight": 700,
122
+ "line-height": "1.05",
123
+ "tracking": "-0.03em"
124
+ },
125
+ "heading": {
126
+ "family": "display",
127
+ "size": "var(--text-xl)",
128
+ "weight": 600,
129
+ "line-height": "1.3"
130
+ },
131
+ "body": { "family": "sans", "size": "var(--text-m)", "weight": 400, "line-height": "1.55" }
132
+ },
133
+ "headings": { "h1": "display", "h2": "heading", "h3": "heading" }
134
+ },
135
+ "animations": {
136
+ "effects": {
137
+ "fade-in": { "kf": "composite", "vars": { "opacity-from": 0 } },
138
+ "slide-up": {
139
+ "kf": "composite",
140
+ "vars": { "translate-y-from": "var(--slide-distance, 2rem)" }
141
+ }
142
+ },
143
+ "journeys": {
144
+ "base": { "fade": { "opacity-from": 0 }, "slide": {} },
145
+ "compose": [["fade"], ["slide"], ["fade", "slide"]]
146
+ }
147
+ }
148
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "my-static-site",
3
+ "version": "0.0.1",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "astro dev",
8
+ "build": "astro build",
9
+ "preview": "astro preview",
10
+ "deploy": "astro build && wrangler deploy",
11
+ "deploy:dev": "astro build && node scripts/dev-wrangler-config.mjs && wrangler deploy --config .wrangler.dev.json",
12
+ "init:github": "node scripts/init-github.mjs",
13
+ "init:hosting": "node scripts/init-hosting.mjs",
14
+ "typecheck": "astro check",
15
+ "build:css": "vitops generate -i design-system.json -f css -o src/styles",
16
+ "lint:design": "vitops lint -i design-system.json -f css --strict",
17
+ "prepare": "vp config"
18
+ },
19
+ "dependencies": {
20
+ "@getvitops/astro": "latest",
21
+ "astro": "^7.1.2"
22
+ },
23
+ "devDependencies": {
24
+ "@astrojs/check": "^0.9.7",
25
+ "@getvitops/cli": "latest",
26
+ "typescript": "^6.0.3",
27
+ "vite": "latest",
28
+ "vite-plus": "latest",
29
+ "wrangler": "^4.111.0"
30
+ },
31
+ "devEngines": {
32
+ "runtime": {
33
+ "name": "node",
34
+ "version": "24.18.0",
35
+ "onFail": "download"
36
+ }
37
+ },
38
+ "packageManager": "pnpm@11.17.0"
39
+ }
@@ -0,0 +1,28 @@
1
+ // Local counterpart to the rewrite the CI dev-deploy workflow does: no adapter
2
+ // regenerates this site's `wrangler.jsonc` (it's a pure static build — Workers
3
+ // Static Assets, no server config to merge), so the checked-in file already
4
+ // IS the deploy config. This just suffixes the worker name and any
5
+ // custom-domain route so a local `pnpm run deploy:dev` never touches the prod
6
+ // worker, writing the result to a gitignored file rather than editing
7
+ // wrangler.jsonc in place.
8
+ //
9
+ // pnpm run deploy:dev → astro build && node scripts/dev-wrangler-config.mjs
10
+ // && wrangler deploy --config .wrangler.dev.json
11
+
12
+ import { readFileSync, writeFileSync } from 'node:fs';
13
+
14
+ const SRC = 'wrangler.jsonc';
15
+ const OUT = '.wrangler.dev.json';
16
+
17
+ const raw = readFileSync(SRC, 'utf8')
18
+ .replace(/\/\/.*$/gm, '')
19
+ .replace(/,(\s*[}\]])/g, '$1');
20
+ const cfg = JSON.parse(raw);
21
+
22
+ cfg.name = `${cfg.name}-dev`;
23
+ cfg.routes = (cfg.routes ?? []).map((r) =>
24
+ r?.pattern ? { ...r, pattern: `dev.${r.pattern}` } : r,
25
+ );
26
+
27
+ writeFileSync(OUT, `${JSON.stringify(cfg, null, 2)}\n`);
28
+ console.log(`Wrote ${OUT}\n name: ${cfg.name}\n routes: ${JSON.stringify(cfg.routes)}`);