@getvitops/create 0.9.0-alpha.3 → 0.9.0-alpha.5
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.
- package/CHANGELOG.md +78 -0
- package/package.json +2 -2
- package/templates/emdash/.agents/skills/setup/SKILL.md +7 -0
- package/templates/emdash/.claude/settings.json +7 -1
- package/templates/emdash/.github/workflows/deploy-prod.yml +1 -1
- package/templates/emdash/.playwright/cli.config.json +7 -0
- package/templates/emdash/AGENTS.md +48 -170
- package/templates/emdash/README.md +21 -21
- package/templates/emdash/_gitignore +11 -8
- package/templates/emdash/package.json +6 -5
- package/templates/emdash/pnpm-workspace.yaml +7 -14
- package/templates/emdash/public/_headers +1 -1
- package/templates/emdash/scripts/pull-content.mjs +1 -1
- package/templates/emdash/site.json +147 -16
- package/templates/emdash/src/layouts/Layout.astro +15 -16
- package/templates/emdash/src/pages/[...slug].astro +1 -1
- package/templates/emdash/src/pages/api/track.ts +1 -1
- package/templates/emdash/src/pages/index.astro +1 -1
- package/templates/static/.agents/skills/setup/SKILL.md +7 -0
- package/templates/static/.claude/settings.json +6 -0
- package/templates/static/.playwright/cli.config.json +7 -0
- package/templates/static/AGENTS.md +36 -124
- package/templates/static/_gitignore +8 -8
- package/templates/static/package.json +4 -3
- package/templates/static/pnpm-workspace.yaml +5 -10
- package/templates/static/site.json +125 -14
|
@@ -33,10 +33,17 @@
|
|
|
33
33
|
},
|
|
34
34
|
"ui-primary": "brand",
|
|
35
35
|
"brand-primary": "brand",
|
|
36
|
-
"info":
|
|
36
|
+
"info": {
|
|
37
|
+
"hue": "sky",
|
|
38
|
+
"solid": 700
|
|
39
|
+
},
|
|
37
40
|
"success": "brand",
|
|
38
41
|
"warning": "sun",
|
|
39
|
-
"danger":
|
|
42
|
+
"danger": {
|
|
43
|
+
"hue": "rose",
|
|
44
|
+
"solid": 700
|
|
45
|
+
},
|
|
46
|
+
"ui-accent": "sun"
|
|
40
47
|
},
|
|
41
48
|
"utilities": ["bg", "text", "icon", "border"]
|
|
42
49
|
},
|
|
@@ -106,6 +113,13 @@
|
|
|
106
113
|
"br": "0.25rem",
|
|
107
114
|
"p": "0.25em 0.5em",
|
|
108
115
|
"fs": "0.75rem"
|
|
116
|
+
},
|
|
117
|
+
"content": {
|
|
118
|
+
"ds": "var(--ds-default)",
|
|
119
|
+
"b": "var(--b-default)",
|
|
120
|
+
"br": "0.5rem",
|
|
121
|
+
"p": "1rem",
|
|
122
|
+
"fs": "var(--fs-default)"
|
|
109
123
|
}
|
|
110
124
|
},
|
|
111
125
|
"z": {
|
|
@@ -115,22 +129,77 @@
|
|
|
115
129
|
"top": 1000
|
|
116
130
|
},
|
|
117
131
|
"items": {
|
|
118
|
-
"
|
|
132
|
+
"btn": {
|
|
119
133
|
"group": "control",
|
|
120
134
|
"element": "button",
|
|
121
|
-
"
|
|
135
|
+
"class": "btn",
|
|
136
|
+
"fill": false,
|
|
137
|
+
"overrides": {
|
|
138
|
+
"b": "1px solid transparent",
|
|
139
|
+
"fs": "inherit"
|
|
140
|
+
},
|
|
141
|
+
"base": {
|
|
142
|
+
"display": "inline-flex",
|
|
143
|
+
"align-items": "center",
|
|
144
|
+
"justify-content": "center",
|
|
145
|
+
"gap": "0.4em",
|
|
146
|
+
"padding": "var(--p-btn-group)",
|
|
147
|
+
"border-radius": "var(--br-btn-group)",
|
|
148
|
+
"border": "var(--b-btn-group)",
|
|
149
|
+
"box-shadow": "var(--ds-btn-group)",
|
|
150
|
+
"background": "transparent",
|
|
151
|
+
"color": "inherit",
|
|
152
|
+
"font-family": "inherit",
|
|
153
|
+
"font-size": "var(--fs-btn-group)",
|
|
154
|
+
"font-weight": "inherit",
|
|
155
|
+
"text-decoration": "none",
|
|
156
|
+
"cursor": "pointer"
|
|
157
|
+
},
|
|
158
|
+
"states": {
|
|
159
|
+
"hover": {
|
|
160
|
+
"step": 1,
|
|
161
|
+
"css": {
|
|
162
|
+
"background-color": "var(--color-bg-surface-muted)"
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
"focus-visible": {
|
|
166
|
+
"ring": true
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
"roles": []
|
|
170
|
+
},
|
|
171
|
+
"cta": {
|
|
172
|
+
"group": "control",
|
|
173
|
+
"class": "cta",
|
|
174
|
+
"fill": true,
|
|
175
|
+
"default_role": "ui-primary",
|
|
176
|
+
"overrides": {
|
|
177
|
+
"p": "0.75em 1.5em",
|
|
178
|
+
"b": "none",
|
|
179
|
+
"ds": "var(--shadow-sm)",
|
|
180
|
+
"fs": "inherit"
|
|
181
|
+
},
|
|
122
182
|
"base": {
|
|
123
|
-
"
|
|
124
|
-
"
|
|
125
|
-
"
|
|
183
|
+
"display": "inline-flex",
|
|
184
|
+
"align-items": "center",
|
|
185
|
+
"justify-content": "center",
|
|
186
|
+
"gap": "0.5em",
|
|
187
|
+
"padding": "var(--p-cta-group)",
|
|
188
|
+
"border-radius": "var(--br-cta-group)",
|
|
189
|
+
"border": "var(--b-cta-group)",
|
|
190
|
+
"font-family": "inherit",
|
|
191
|
+
"font-size": "var(--fs-cta-group)",
|
|
126
192
|
"font-weight": "600",
|
|
127
|
-
"
|
|
193
|
+
"line-height": "inherit",
|
|
194
|
+
"text-decoration": "none",
|
|
128
195
|
"cursor": "pointer",
|
|
129
|
-
"
|
|
196
|
+
"color": "var(--color-text-on-ui-primary)",
|
|
197
|
+
"box-shadow": "var(--ds-cta-group)"
|
|
130
198
|
},
|
|
131
199
|
"states": {
|
|
132
200
|
"hover": {
|
|
133
|
-
"step": 1
|
|
201
|
+
"step": 1,
|
|
202
|
+
"lift": "1px"
|
|
134
203
|
},
|
|
135
204
|
"active": {
|
|
136
205
|
"scale": 0.97
|
|
@@ -139,8 +208,27 @@
|
|
|
139
208
|
"ring": true
|
|
140
209
|
}
|
|
141
210
|
},
|
|
142
|
-
"roles": ["success", "danger", "warning", "info"]
|
|
143
|
-
|
|
211
|
+
"roles": ["success", "danger", "warning", "info"]
|
|
212
|
+
},
|
|
213
|
+
"link": {
|
|
214
|
+
"group": "control",
|
|
215
|
+
"element": "a",
|
|
216
|
+
"class": "link",
|
|
217
|
+
"default_role": "ui-primary",
|
|
218
|
+
"base": {
|
|
219
|
+
"color": "var(--color-text-ui-primary)",
|
|
220
|
+
"text-decoration": "underline",
|
|
221
|
+
"text-underline-offset": "0.15em"
|
|
222
|
+
},
|
|
223
|
+
"states": {
|
|
224
|
+
"hover": {
|
|
225
|
+
"step": 1
|
|
226
|
+
},
|
|
227
|
+
"focus-visible": {
|
|
228
|
+
"ring": true
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
"roles": []
|
|
144
232
|
},
|
|
145
233
|
"card": {
|
|
146
234
|
"group": "panel",
|
|
@@ -199,6 +287,23 @@
|
|
|
199
287
|
},
|
|
200
288
|
"states": {},
|
|
201
289
|
"roles": ["success", "danger", "warning", "info"]
|
|
290
|
+
},
|
|
291
|
+
"details": {
|
|
292
|
+
"group": "content"
|
|
293
|
+
},
|
|
294
|
+
"steps": {
|
|
295
|
+
"group": "content",
|
|
296
|
+
"class": "steps",
|
|
297
|
+
"overrides": {
|
|
298
|
+
"b": "1px solid var(--color-border-surface-muted)",
|
|
299
|
+
"br": "0.75rem",
|
|
300
|
+
"p": "1.5rem",
|
|
301
|
+
"ds": "none"
|
|
302
|
+
},
|
|
303
|
+
"base": {
|
|
304
|
+
"--steps-marker-size": "2.5rem",
|
|
305
|
+
"--steps-line-width": "2px"
|
|
306
|
+
}
|
|
202
307
|
}
|
|
203
308
|
}
|
|
204
309
|
},
|
|
@@ -309,14 +414,40 @@
|
|
|
309
414
|
},
|
|
310
415
|
"site": {
|
|
311
416
|
"defaultLocale": "en",
|
|
417
|
+
"chrome": {
|
|
418
|
+
"masthead": {
|
|
419
|
+
"position": "sticky",
|
|
420
|
+
"behavior": "always",
|
|
421
|
+
"surface": "glass",
|
|
422
|
+
"layout": "full",
|
|
423
|
+
"elevation": { "shadow": "sm", "onScroll": true },
|
|
424
|
+
"height": "4rem"
|
|
425
|
+
},
|
|
426
|
+
"nav": { "compact": "drawer", "drawerSide": "end" }
|
|
427
|
+
},
|
|
312
428
|
"templates": {
|
|
313
429
|
"contact": {
|
|
314
430
|
"type": "form",
|
|
315
431
|
"fields": [
|
|
316
|
-
{
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
432
|
+
{
|
|
433
|
+
"name": "name",
|
|
434
|
+
"type": "text",
|
|
435
|
+
"required": true
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
"name": "email",
|
|
439
|
+
"type": "email",
|
|
440
|
+
"required": true
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
"name": "tel",
|
|
444
|
+
"type": "tel"
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
"name": "message",
|
|
448
|
+
"type": "textarea",
|
|
449
|
+
"required": true
|
|
450
|
+
}
|
|
320
451
|
]
|
|
321
452
|
}
|
|
322
453
|
},
|
|
@@ -5,9 +5,11 @@ import { getMenu, getSiteSettings } from 'emdash';
|
|
|
5
5
|
import { createPublicPageContext } from 'emdash/page';
|
|
6
6
|
import SiteFooter from '@getvitops/astro/components/SiteFooter.astro';
|
|
7
7
|
import SiteNav from '@getvitops/astro/components/SiteNav.astro';
|
|
8
|
+
import Masthead from '@getvitops/astro/components/Masthead.astro';
|
|
9
|
+
import { resolveNavOptions } from '@getvitops/astro/components/masthead.ts';
|
|
8
10
|
import { loadNavMenus } from '@getvitops/astro/components/sitenav.ts';
|
|
9
11
|
import { EmDashHead } from 'emdash/ui';
|
|
10
|
-
import { VitopsWidgetArea } from '@getvitops/emdash/astro';
|
|
12
|
+
import { VitopsMegaPanel, VitopsWidgetArea } from '@getvitops/emdash/astro';
|
|
11
13
|
import config from '../../site.json' with { type: 'json' };
|
|
12
14
|
// Design-system CSS, layout-scoped (vitops css.inject: false): only pages
|
|
13
15
|
// rendered through this layout get it — keeps it out of /_emdash/admin, while
|
|
@@ -75,18 +77,19 @@ const orgName = config.organization?.name || siteTitle;
|
|
|
75
77
|
<body>
|
|
76
78
|
<!-- Widget areas (Widgets in the admin): the same content wherever they appear. -->
|
|
77
79
|
<VitopsWidgetArea name="announcement" class="centered" />
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
<
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
80
|
+
<!-- The masthead's look and the nav's behaviour come from `site.chrome` in site.json
|
|
81
|
+
(position, hide-on-scroll, glass, inset, shadow, drawer vs dropdown). A prop here
|
|
82
|
+
overrides one field for this layout. -->
|
|
83
|
+
<Masthead config={config}>
|
|
84
|
+
<a slot="brand" class="brand flex items-center" href="/" aria-label={`${siteTitle} home`}>
|
|
85
|
+
<span class="brand-mark" set:html={logo} aria-hidden="true" />
|
|
86
|
+
<span class="font-heading">{siteTitle}</span>
|
|
87
|
+
</a>
|
|
88
|
+
<div class="header-end flex items-center">
|
|
89
|
+
<SiteNav {...nav} {...resolveNavOptions(config)} megaPanel={VitopsMegaPanel} />
|
|
90
|
+
<wc-color-scheme-toggle></wc-color-scheme-toggle>
|
|
88
91
|
</div>
|
|
89
|
-
</
|
|
92
|
+
</Masthead>
|
|
90
93
|
|
|
91
94
|
<main class="centered rhythm">
|
|
92
95
|
<slot />
|
|
@@ -109,10 +112,6 @@ const orgName = config.organization?.name || siteTitle;
|
|
|
109
112
|
block-size: 1.75rem;
|
|
110
113
|
}
|
|
111
114
|
|
|
112
|
-
.navbar {
|
|
113
|
-
block-size: 64px;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
115
|
.header-end {
|
|
117
116
|
gap: var(--space-s, 0.75rem);
|
|
118
117
|
}
|
|
@@ -8,7 +8,7 @@ import Layout from '../layouts/Layout.astro';
|
|
|
8
8
|
// the content database — `scripts/pull-content.mjs` loads production's into the
|
|
9
9
|
// local build database first (it is part of `deploy`/`deploy:dev`) — so an edit
|
|
10
10
|
// in the admin goes live on the next rebuild, which a publish webhook triggers
|
|
11
|
-
// (see .agents/skills/content-and-deploys).
|
|
11
|
+
// (see .agents/skills/emdash-content-and-deploys).
|
|
12
12
|
//
|
|
13
13
|
// There is no `Astro.rewrite('/404')` here and no on-demand fallback: a URL that
|
|
14
14
|
// isn't in the list below simply has no route, so Astro serves the prerendered
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* The site's one on-demand endpoint: contact-form posts (the `vitops_form` block) and the
|
|
3
3
|
* conversion beacons (`<Tracking />`, `tel:`/`mailto:` clicks) all arrive here.
|
|
4
4
|
*
|
|
5
|
-
* Every public page is prerendered (see .agents/skills/content-and-deploys); this route sets
|
|
5
|
+
* Every public page is prerendered (see .agents/skills/emdash-content-and-deploys); this route sets
|
|
6
6
|
* `prerender = false` because it has to run on each request. It is the one exception, and the
|
|
7
7
|
* Cloudflare adapter handles it in the Worker beside the EmDash admin.
|
|
8
8
|
*
|
|
@@ -5,7 +5,7 @@ import Layout from '../layouts/Layout.astro';
|
|
|
5
5
|
|
|
6
6
|
// Prerendered, like every page in this template: written to static HTML at build
|
|
7
7
|
// time from the `home` entry (seed/seed.json → pages/home). Edit it in the admin;
|
|
8
|
-
// a publish triggers a rebuild that bakes the change in (.agents/skills/content-and-deploys,
|
|
8
|
+
// a publish triggers a rebuild that bakes the change in (.agents/skills/emdash-content-and-deploys,
|
|
9
9
|
// "Rendering and freshness"). The Vitops blocks from @getvitops/emdash render automatically —
|
|
10
10
|
// EmDash merges the plugin's block components into <PortableText>.
|
|
11
11
|
//
|
|
@@ -59,3 +59,10 @@ report that verbatim rather than guessing at a fix. A step reported as
|
|
|
59
59
|
"blocked" is not a failure to retry; it is waiting on one of the hard stops
|
|
60
60
|
above, or on a `site.json` field the user still needs to fill in (stage 5,
|
|
61
61
|
Configuration).
|
|
62
|
+
|
|
63
|
+
## Naming the project
|
|
64
|
+
|
|
65
|
+
`vp create` takes the package name from the target directory and invents a random slug when none
|
|
66
|
+
is given, so pass one: `vp create @getvitops:<template> --directory <client-slug>`. `wrangler.jsonc`'s
|
|
67
|
+
`name` (and on EmDash the D1 `database_name` and R2 `bucket_name`) are separate and still say what
|
|
68
|
+
the template shipped; rename them to match before the first deploy.
|
|
@@ -3,138 +3,50 @@
|
|
|
3
3
|
Built with the Vitops design system (`@getvitops/*`); tokens and site facts live in `site.json`.
|
|
4
4
|
Prefer its classes and patterns over hand-written CSS. Load the skill that matches the task:
|
|
5
5
|
|
|
6
|
-
- [
|
|
7
|
-
- [
|
|
8
|
-
- [csp](.agents/skills/csp/SKILL.md) — Use when changing `public/_headers`, adding an embed, tracking snippet or third-party
|
|
9
|
-
- [
|
|
10
|
-
- [vitops-
|
|
6
|
+
- [vitops-ads](.agents/skills/vitops-ads/SKILL.md) — Use when adding or changing a Google/Meta/LinkedIn/TikTok/Microsoft/Reddit/Pinterest/Snapchat pixel
|
|
7
|
+
- [vitops-consent](.agents/skills/vitops-consent/SKILL.md) — Use before gating, adding or changing any non-essential third-party tag, cookie, embed
|
|
8
|
+
- [vitops-csp](.agents/skills/vitops-csp/SKILL.md) — Use when changing `public/_headers`, adding an embed, tracking snippet or third-party script, turning the CSP on
|
|
9
|
+
- [vitops-design-system](.agents/skills/vitops-design-system/SKILL.md) — Use when styling or authoring pages or components (choosing utility/pattern classes, colours, spacing, typography)
|
|
10
|
+
- [vitops-see-the-page](.agents/skills/vitops-see-the-page/SKILL.md) — How to look at a rendered page of this site
|
|
11
11
|
|
|
12
|
-
Reference, rendered from this project: `vitops docs
|
|
13
|
-
<!-- managed by `vitops agents sync` · @getvitops/cli@8.3.0-alpha.2 — edit outside this block -->
|
|
12
|
+
Reference, rendered from this project: `vp exec vitops docs [topic]` (no topic lists them).
|
|
14
13
|
<!-- vitops:end -->
|
|
15
14
|
|
|
16
|
-
This is a static Astro website styled by the Vitops design system, deployed
|
|
17
|
-
|
|
15
|
+
This is a static Astro website styled by the Vitops design system, deployed as Cloudflare Workers
|
|
16
|
+
static assets (no server runtime, no database).
|
|
18
17
|
|
|
19
18
|
## Ground rules
|
|
20
19
|
|
|
21
|
-
- `site.json` is the single source of truth
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
`
|
|
28
|
-
- `
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
| `max-width` + `margin-inline: auto` | **`centered`** |
|
|
40
|
-
| `padding-block` on a section | **`region`** |
|
|
41
|
-
| margins between headings/paragraphs/lists | **`rhythm`** |
|
|
42
|
-
| `display: grid` + `grid-template-columns: repeat(n, …)` | **`subgrid`** |
|
|
43
|
-
| `repeat(auto-fit, minmax(…))` | **`grid-auto`** |
|
|
44
|
-
| `display: flex` + `gap` for a row of controls | **`cluster`** |
|
|
45
|
-
- Every page is prerendered by default (`output: 'static'`) — there is no
|
|
46
|
-
server to fall back to, so nothing here can read request-time data
|
|
47
|
-
(cookies, headers, query params) at render time. If a page genuinely needs
|
|
48
|
-
that, it needs an adapter and a different template — this one stays pure
|
|
49
|
-
static on purpose.
|
|
50
|
-
- **`SETUP.html` is the client-onboarding checklist.** When working it via the
|
|
51
|
-
`.agents/skills/setup/` skill, tick a box only for a step you actually
|
|
52
|
-
completed — never on the operator's behalf for a step marked human-only
|
|
53
|
-
(the Cloudflare API token, the domain cutover, publishing legal documents).
|
|
54
|
-
|
|
55
|
-
## Branch model
|
|
56
|
-
|
|
57
|
-
- Work on **`dev`** (the integration branch). Every push auto-deploys the
|
|
58
|
-
isolated `-dev` worker (`dev.<domain>` with a custom domain).
|
|
59
|
-
- **`main`** is production and branch-protected — never push or merge to it
|
|
60
|
-
directly. Production ships only via the manual **promote** flow:
|
|
61
|
-
`.github/workflows/promote.yml`, dispatched manually, opens a `dev → main`
|
|
62
|
-
PR with auto-merge; merging deploys prod. Only run it when the user
|
|
63
|
-
explicitly asks to promote/ship to production.
|
|
64
|
-
|
|
65
|
-
## Labels: badge and tag
|
|
66
|
-
|
|
67
|
-
Two label patterns, both enabled in `site.json`'s `patterns.items`: **`badge`** is a
|
|
68
|
-
static label (a status, count or category) and **`tag`** is a label that may be
|
|
69
|
-
static _or_ dynamic (editable, dismissable, in a `tag-list`). Don't invent a third
|
|
70
|
-
name — `chip` and `pill` are not part of this vocabulary. The button pattern's class
|
|
71
|
-
is `btn` (`<a class="btn">` is styled, not just a bare `<button>`).
|
|
72
|
-
|
|
73
|
-
## Content Security Policy
|
|
74
|
-
|
|
75
|
-
`public/_headers` ships a **`Content-Security-Policy-Report-Only`** header for every
|
|
76
|
-
page (they are all static assets): violations are logged to the browser console and
|
|
77
|
-
nothing is blocked, so it can't break a page. Its `script-src` is `'self'` plus the
|
|
78
|
-
SHA-256 of each inline script `<Head />` emits (the colour-scheme bootstrap and the
|
|
79
|
-
consent-gate stub), with no `'unsafe-inline'`. `contentSecurityPolicy()` and
|
|
80
|
-
`inlineScriptHashes()` from `@getvitops/astro` produce the same strings.
|
|
81
|
-
|
|
82
|
-
Before enforcing it (rename the header to `Content-Security-Policy`), browse the pages
|
|
83
|
-
with the console open: add the origins of any third-party tag the consent gate
|
|
84
|
-
activates to `script-src` / `connect-src`, any embed to `frame-src`, and hash any
|
|
85
|
-
inline script you add yourself. Hashes rather than nonces because a static page has no
|
|
86
|
-
per-request response to carry one.
|
|
87
|
-
|
|
88
|
-
## Skills
|
|
89
|
-
|
|
90
|
-
`@getvitops/skills` ships agent skills that update with the package. `skills experimental_sync` (run
|
|
91
|
-
by `prepare`, so by `vp install`) links them into `.agents/skills/` and `.claude/skills/`; they are
|
|
92
|
-
gitignored. The set is written for EmDash sites, so `csp` is the one that applies here. A skill you
|
|
93
|
-
write yourself with the same name is never replaced. `setup` is this site's own.
|
|
20
|
+
- `site.json` is the single source of truth: organization + site facts, and the design system under
|
|
21
|
+
`designSystem.themes.default`. Never edit `src/styles/`: it is generated from `site.json` on every
|
|
22
|
+
dev/build and gitignored.
|
|
23
|
+
- Every page is prerendered (`output: 'static'`): nothing can read request-time data (cookies,
|
|
24
|
+
headers, query params). A page that needs that needs an adapter and a different template.
|
|
25
|
+
- Prefer framework classes (utilities, patterns, type roles like `font-heading`) over bespoke CSS.
|
|
26
|
+
`vpr lint:design` fails the pre-commit hook on unresolvable classes and layout primitives you
|
|
27
|
+
hand-rolled (`centered`, `region`, `rhythm`, `subgrid`, `grid-auto`, `cluster` exist for those).
|
|
28
|
+
- `src/assets/placeholder/` is wireframe stand-in imagery; delete it once real assets land.
|
|
29
|
+
- `SETUP.html` is the onboarding checklist (the `setup` skill). Tick a box only for a step you
|
|
30
|
+
completed, never for a human-only one (the Cloudflare API token, domain cutover, legal documents).
|
|
31
|
+
|
|
32
|
+
## Branches
|
|
33
|
+
|
|
34
|
+
Work on **`dev`**; every push auto-deploys the isolated `-dev` worker. **`main`** is production and
|
|
35
|
+
protected: never push or merge to it directly; production ships only through the manual `promote`
|
|
36
|
+
workflow (`.github/workflows/promote.yml`), only when the user explicitly asks. Shipping is not a
|
|
37
|
+
package release: no changeset or version bump.
|
|
94
38
|
|
|
95
39
|
## Commands
|
|
96
40
|
|
|
97
|
-
This is a **Vite+** project: use `vp` (and
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
| run a `package.json` script | `vpr <script>` (alias for `vp run <script>`) |
|
|
105
|
-
| run a locally installed binary | `vp exec <bin>` (e.g. `vp exec vitops docs classes`) |
|
|
106
|
-
| run a one-off package without installing | `vp dlx <pkg>` |
|
|
107
|
-
| format + lint + typecheck (files) | `vp check` |
|
|
108
|
-
| typecheck Astro (`.astro` files) | `vpr typecheck` |
|
|
109
|
-
|
|
110
|
-
**Scripts that wrap Astro must go through `vpr`.** `vp dev` / `vp build` run Vite
|
|
111
|
-
directly and skip Astro, so use `vpr dev`, `vpr build`, `vpr preview`.
|
|
112
|
-
|
|
113
|
-
**`vpr dev` returns immediately.** `astro dev` now starts the server in the
|
|
114
|
-
background. Check it with `vp exec astro dev status`, read its output with
|
|
115
|
-
`vp exec astro dev logs --follow`, and stop it with `vp exec astro dev stop`; the
|
|
116
|
-
site is at <http://localhost:4321>. Don't wait on it as if it were a foreground
|
|
117
|
-
process.
|
|
118
|
-
|
|
119
|
-
| Script | What it does |
|
|
120
|
-
| ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
|
|
121
|
-
| `vpr dev` | local dev |
|
|
122
|
-
| `vpr build:css` | regenerate the framework CSS from `site.json` |
|
|
123
|
-
| `vpr deploy` | build + `wrangler deploy` to prod |
|
|
124
|
-
| `vpr deploy:dev` | build + deploy the isolated dev worker |
|
|
125
|
-
| `vpr init:github` | one-time: create + push the GitHub repo (main + dev, dev default, branch protection + environment policy). Only when the user asks. |
|
|
126
|
-
| `vpr init:hosting` | one-time: read the Cloudflare account id and set it as a repo secret. Only when the user asks. |
|
|
127
|
-
| `vp exec vitops validate site.json` | schema-check the site config |
|
|
128
|
-
| `vp exec vitops lint -i site.json -f css` | find framework classes in source that resolve to nothing under this format |
|
|
41
|
+
This is a **Vite+** project: use `vp` (and `vpr` for scripts), not `pnpm`/`npm`/`npx`. Scripts that
|
|
42
|
+
wrap Astro go through `vpr` (`vpr dev`, `vpr build`), because `vp dev`/`vp build` skip Astro.
|
|
43
|
+
`vpr dev` returns immediately (the server runs in the background): check it with
|
|
44
|
+
`vp exec astro dev status`, read `vp exec astro dev logs --follow`, stop with
|
|
45
|
+
`vp exec astro dev stop`; the site is at <http://localhost:4321>. `package.json` lists the scripts;
|
|
46
|
+
`vp check` and `vpr typecheck` verify a change. `vpr init:github` and `vpr init:hosting` are one-time
|
|
47
|
+
setup, only when the user asks.
|
|
129
48
|
|
|
130
|
-
|
|
131
|
-
version bump: ship by committing to `dev` (auto-deploys the dev worker) and then
|
|
132
|
-
running the **promote** workflow. `vp` has no `vp change` / `vp pm change` command
|
|
133
|
-
(checked against vp 1.5.0); for a _package_ it does have `vp pm version`,
|
|
134
|
-
`vp pm publish` and `vp pm stage`.
|
|
49
|
+
## Where to look
|
|
135
50
|
|
|
136
|
-
**
|
|
137
|
-
|
|
138
|
-
`vp create @getvitops:static --directory <client-slug>`. `wrangler.jsonc`'s `name`
|
|
139
|
-
is separate and still says what the template shipped — rename it to match before
|
|
140
|
-
the first deploy.
|
|
51
|
+
- **Skills** are listed in the block at the top; load the one matching the task before starting.
|
|
52
|
+
- **Reference** for this project's own tokens, classes and config: `vp exec vitops docs`.
|
|
@@ -27,11 +27,11 @@ public/vitops/
|
|
|
27
27
|
.DS_Store
|
|
28
28
|
|
|
29
29
|
# agent skills linked from @getvitops/skills by `skills experimental_sync` (see skills-lock.json)
|
|
30
|
-
|
|
31
|
-
.agents/skills/
|
|
32
|
-
.agents/skills/
|
|
33
|
-
.
|
|
34
|
-
.claude/skills/
|
|
35
|
-
|
|
36
|
-
.claude/skills/
|
|
37
|
-
.
|
|
30
|
+
# (the `vitops-` and `emdash-` prefixes are reserved for toolkit skills)
|
|
31
|
+
.agents/skills/vitops-*
|
|
32
|
+
.agents/skills/emdash-*
|
|
33
|
+
.claude/skills/vitops-*
|
|
34
|
+
.claude/skills/emdash-*
|
|
35
|
+
# playwright-cli: skill regenerated by `prepare`; output is per-session scratch
|
|
36
|
+
.claude/skills/playwright-cli
|
|
37
|
+
.playwright-cli/
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"build:css": "vitops generate -i site.json -f css -o src/styles",
|
|
17
17
|
"lint:design": "vitops lint -i site.json -f css --strict",
|
|
18
18
|
"sop": "vitops generate -i site.json -f css -o .vitops/sop",
|
|
19
|
-
"prepare": "vp config && skills experimental_sync -y -a claude-code --no-frozen-lockfile && vitops agents sync -i site.json"
|
|
19
|
+
"prepare": "vp config && skills experimental_sync -y -a claude-code --no-frozen-lockfile && playwright cli install --skills && vitops agents sync -i site.json"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@getvitops/astro": "latest",
|
|
@@ -26,10 +26,11 @@
|
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@astrojs/check": "^0.9.12",
|
|
28
28
|
"@getvitops/cli": "latest",
|
|
29
|
+
"playwright": "^1.62.1",
|
|
29
30
|
"skills": "^1.7.6",
|
|
30
31
|
"typescript": "^6.0.3",
|
|
31
|
-
"vite": "
|
|
32
|
-
"vite-plus": "
|
|
32
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@^1.5.1",
|
|
33
|
+
"vite-plus": "^1.5.1",
|
|
33
34
|
"wrangler": "^4.111.0"
|
|
34
35
|
},
|
|
35
36
|
"devEngines": {
|
|
@@ -5,17 +5,12 @@ allowBuilds:
|
|
|
5
5
|
workerd: true
|
|
6
6
|
sharp: false
|
|
7
7
|
|
|
8
|
-
# Supply-chain hardening: nothing installs within 3 days of its publish
|
|
9
|
-
#
|
|
8
|
+
# Supply-chain hardening: nothing installs within 3 days of its publish, and no non-registry
|
|
9
|
+
# transitive sources. Only our own lockstep `@getvitops/*` is exempt. Do NOT exempt a third-party
|
|
10
|
+
# toolchain: an exempt package's exact pins are not exempt (vite-plus pins `@oxc-project/*`
|
|
11
|
+
# exactly), so the install fails whenever one is fresher than the window. A security patch may be
|
|
12
|
+
# admitted with an exact `name@x.y.z` line and a dated reason; remove it once it matures.
|
|
10
13
|
minimumReleaseAge: 4320
|
|
11
14
|
minimumReleaseAgeExclude:
|
|
12
15
|
- '@getvitops/*'
|
|
13
|
-
- vite-plus
|
|
14
|
-
- '@voidzero-dev/*'
|
|
15
|
-
- oxlint
|
|
16
|
-
- '@oxlint/*'
|
|
17
|
-
- oxlint-tsgolint
|
|
18
|
-
- '@oxlint-tsgolint/*'
|
|
19
|
-
- oxfmt
|
|
20
|
-
- '@oxfmt/*'
|
|
21
16
|
blockExoticSubdeps: true
|