webjs-scaffold-sync
Skill28 starsChanged 36 days agoMITView on GitHub
Use this skill whenever a change affects what `webjs create` GENERATES (a new or changed gallery/showcase demo, a new template, a changed generated file like the layout/home/theme/schema, a new convention that belongs in generated apps, a new scaffold-shipped config/hook) OR what the agent skill `.agents/skills/webjs/` (SKILL.md + references/) TEACHES, OR when the user asks to sync the scaffold or the skill, "update all three templates", check the scaffold is consistent, keep the skill in sync with framework features, or teach agents how to use WebJs. The scaffold teaches AI agents through TWO surfaces that must stay in sync with the framework: the agent skill `.agents/skills/webjs/` (the DURABLE teacher, the only surface that survives `gallery:clear`) and the runnable gallery (DISPOSABLE, removed by `gallery:clear`). A feature change usually needs BOTH. A change to either must propagate in lockstep across the skill, the generators, the per-agent rule files, the scaffold tests, the framework docs that describe the scaffold, and the preview/example apps. This skill is the authoritative map of every surface plus the change-type to surface mapping, and the mandatory "generate + boot + check" verification, so no surface is silently skipped. Complements webjs-doc-sync (which owns framework API/behaviour docs); this skill owns what the scaffold and the skill teach.
In this repository16 other files it gives its agents.
- AGENTS.mdAGENTS.md
- gallery/AGENTS.mdAGENTS.md
- website/AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- website/CLAUDE.mdCLAUDE.md
- webjsSkill
- pr-reviewSkill
- use-railwaySkill
- webjs-blog-writeSkill
- webjs-doc-syncSkill
- webjs-file-issueSkill
- webjs-instagram-postSkill
- webjs-list-todosSkill
- webjs-ready-for-devSkill
- webjs-research-recordSkill
- webjs-start-workSkill
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 3 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 97
Treat this as the universe.
- Distinctive: line 200
Update every surface the mapping says applies.
- Distinctive: line 202
MUST surface and fix every copy, in the rule files AND the framework docs.
- Very specific: line 216
Run the scaffold tests (node --test 'test/scaffolds/*.test.js') and add/adjust assertions (a new demo in the FEATURES list, a per-template …
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Keep every scaffold surface in sync with what webjs create generates
The scaffold is the primary way AI agents learn WebJs, through TWO teaching surfaces that must stay in sync with the framework:
- The agent skill
.agents/skills/webjs/(SKILL.md + references/): the DURABLE teacher. It is the ONE canonical source (bundled into every scaffold at prepack viascripts/sync-scaffold-skill.mjs, and the repo's own agent guide). Crucially,gallery:clearstrips the whole gallery to a blank slate, so the skill is the ONLY teaching surface that SURVIVES, and after a clear it is the agent's sole reference. A feature the skill does not teach is lost the moment an agent clears the gallery. - The gallery (the repo-root
gallery/**app): runnable, densely commented demos an agent learns the idioms from by reading and running, then adapts. It is DISPOSABLE (removed bygallery:clearbefore real work begins). It lives ONCE, at the repo root, as a live workspace app you can boot and test (npm run dev:gallery,npm test --workspace=@webjsdev/gallery).packages/cli/prepackbundles it intopackages/cli/templates/gallery/for the tarball andpostpackdeletes that copy, so never edit or commit there.
So a change to a WebJs FEATURE usually needs BOTH: the skill updated (the durable
pattern) AND a gallery demo (the runnable illustration). A change to what
webjs create emits is a first-class change with MANY surfaces, and the
recurring failure is updating one (usually a template file, or the gallery but
not the skill) while the skill, the per-agent rule files, the scaffold tests, the
framework docs, and the preview apps drift behind. This skill closes that gap.
It is the sibling of webjs-doc-sync. Division of labour:
- webjs-doc-sync owns the framework's API/behaviour docs (the root
AGENTS.mdAPI sections,agent-docs/*.md, docs-site topic pages, the marketing website). - webjs-scaffold-sync (this skill) owns what the scaffold GENERATES and the surfaces that DESCRIBE the scaffold.
They overlap on two surfaces (the scaffold's per-agent rule files, and the template matrix in the framework docs/README). Whichever skill reaches that surface must update it; when in doubt run both.
Enforcement is TWO tiers, deliberately mirroring how tests are enforced (a commit-time floor plus an un-skippable CI gate):
- Tier 1, the commit floor.
.claude/hooks/require-scaffold-with-src.shBLOCKS a commit that stages framework-feature source (packages/(core|server|cli)/src) with no teaching surface in the same commit (escape hatchWEBJS_NO_SCAFFOLD_GATE=1). A teaching surface is EITHER the scaffold (packages/cli/templatesorpackages/cli/lib) OR the agent skill (.agents/skills/webjs/), since the skill is the durable half of the teaching pair. Like the test commit gate, it only proves you touched a teaching file; it cannot tell a real demo from a doc bullet, nor that you updated BOTH the gallery and the skill where both were needed, which is exactly how #848 slipped (forbidden()/unauthorized() staged doc bullets, shipped no gallery demo). - Tier 2, the CI coverage gate.
test/scaffolds/gallery-coverage.test.jsreconciles the LIVE framework surface against the hand-curatedtest/scaffolds/gallery-coverage.jsonmanifest and FAILS when a new surface is neither demoed nor exempted. It gates THREE surfaces:@webjsdev/coreexports (a{ demo }pointing at a gallery file that references it),@webjsdev/serverexports ({ demoed: true }, verified by a generated app importing it), and routing convention files (the stems the router parses, DERIVED frompackages/server/src/router.jsso a newstem === '...'branch auto-appears, each demonstrated by a file in a generated app). Every entry isdemo/demoedor{ exempt }with a reason (internal: ...for plumbing,deferred: ...for an agent-facing surface not yet demoed). It runs on everynpm testand in CI, so it cannot be skipped with a local--no-verify, the analogue of "a test must exist AND pass": a new export or convention turns CI red until it is classified. When you add or rename a core/server export, or add a routing convention file the router parses, update the manifest (a demo, or an honest exemption), the same reflex as writing a test.
THIS skill does the substantive per-surface judgment and the generate-boot-check verification that neither tier can automate.
The complete scaffold surface map
Treat this as the universe. For any scaffold change, decide per surface whether it applies, then update or consciously skip each.
- The agent skill
.agents/skills/webjs/(the DURABLE teacher, canonical at the repo root, bundled into every scaffold at prepack). It is the surface most likely to be forgotten and the most important to keep current, because it is the ONLY teaching surface that survivesgallery:clear. A new feature, export, idiom, or convention MUST be taught here so an agent building AFTER a clear still learns it:.agents/skills/webjs/SKILL.md(the router: add the concept to the right "what this covers" line and route to the reference)..agents/skills/webjs/references/*.md(the focused reference the feature belongs to, e.g.data-and-actions.md,client-router-and-streaming.md,components.md,styling.md,built-ins.md). Add the API + the idiom + the gotcha, matching the depth of the sibling entries.- Edit the repo-root copy;
scripts/sync-scaffold-skill.mjsbundles it intotemplates/at prepack (do NOT hand-edit a bundled copy).
- The generators (the code that writes the app):
packages/cli/lib/create.js(the main generator: layout, home page, the theme block, db/schema, the full-stack gallery wiring, the per-template gates likeisApi/isFullStack/!isApi).packages/cli/lib/api-gallery.js(the api backend-features showcase). Auth is a full-stack GALLERY card now (gallery/{app/features/auth, modules/auth}), pruned bygallery:clear, not a separate template.- The
gallery:clearreset scripts (BOTH templates, MANDATORY parity).packages/cli/templates/scripts/clear-gallery.mjs(full-stack) strips the app to a barebones blank slate (the gallery routes + modules, the example design systemcomponents/ui/,lib/utils/ui.ts, the example theme-toggle + its layout wiring, the example tests, empty leftover dirs), keeping only the buildable base + the skill.packages/cli/templates/scripts/clear-api-gallery.mjs(theapitemplate) does the same for the backend showcase (app/api/features, the demo modules,env.ts, the widgets test), keeping the health + users base. RULE: any NEW gallery artifact (a route, a module, a shared component, a lib helper, a schema table) MUST be added to the matching clear script's removal list in the SAME change, orgallery:clearleaves it behind and the app is not a blank slate. This is enforced bytest/scaffolds/scaffold-gallery.test.js(full-stack: assertsmodules/andcomponents/are EMPTY after clear, so a forgotten module/component fails) and the api clear test in the same file; run them after any gallery change. - Any future
*-template.js/*-gallery.jssplit out for escaping sanity.
- The verbatim template files copied into every app:
- The repo-root
gallery/**app (the UI feature gallery + example app). Its own shell (app/layout.ts,app/page.ts,components/theme-toggle.ts,lib/utils/cn.ts) is NOT payload: the generator writes those itself, so both the copy and the prepack bundle filter them viapackages/cli/lib/gallery-shell-files.js. Add a file there if the gallery ever needs another app-only shell file. packages/cli/templates/**(everything else copied per app:lib/utils/ui.ts,public/,tsconfig.json,gitignore,.hooks/, the metadata/route stubs).
- The repo-root
- The per-agent rule files (LOCKSTEP: all carry the SAME rules in each
agent's format, the #134/#136 divergence lesson). A convention/workflow change
for generated apps must land in ALL of them together:
packages/cli/templates/AGENTS.mdpackages/cli/templates/CLAUDE.mdpackages/cli/templates/CONVENTIONS.mdpackages/cli/templates/.cursorrulespackages/cli/templates/.github/copilot-instructions.mdpackages/cli/templates/.agents/rules/workflow.mdpackages/cli/templates/.gemini/**,.opencode/**,.claude/**(whatever per-agent rule files the scaffold currently ships; enumerate, do not assume)
- The scaffold tests:
test/scaffolds/*.test.js(e.g.scaffold-gallery,scaffold-ui-integration). A new demo/template/generated-file assertion goes here, including the counterfactual (a per-template exclusion test). - The framework docs that DESCRIBE the scaffold (shared with doc-sync):
- Root
AGENTS.md"Scaffolding" section. - The docs site:
website/app/(site)/docs/getting-started/page.ts(+backend-only,ai-first,conventionswhere they describe generated structure). README.md(the template matrix + the "scaffold is the tutorial" note).
- Root
- The CLI surface:
packages/cli/--templatevalidation +--help/usage text when a template or flag is added or renamed. - The preview / example / dogfood apps:
examples/blog/and any in-repo apps, plus the local preview apps the user tests, when a convention they demonstrate changes.
Change-type to surface mapping
| Change | Surfaces that MUST be checked |
| New / changed WebJs feature, export, idiom, or convention an agent must know | the agent skill .agents/skills/webjs/ FIRST (SKILL.md routing line + the right references/*.md), the DURABLE teacher that survives gallery:clear, THEN a gallery demo (surface 2/3). Skill-without-demo means no runnable example; demo-without-skill means the pattern is LOST the moment an agent clears the gallery. A feature needs BOTH. |
| New / changed gallery or showcase demo | the template file(s) or generator strings for the demo + the home-page features/index array + the scaffold AGENTS.md gallery list + the matching gallery:clear removal list (clear-gallery.mjs for full-stack, clear-api-gallery.mjs for api, so the new demo/module/component/lib artifact is stripped to a blank slate) + test/scaffolds/* FEATURES/assertions + generate + boot the affected template + run gallery:clear and confirm a blank slate |
| Removed / renamed gallery artifact (a demo route, a module, a shared component, a lib helper, a schema table the gallery added) | the matching gallery:clear script's removal list (add the new path; remove a stale one) + the blank-slate clear test (test/scaffolds/scaffold-gallery.test.js) + generate + run the clear + assert nothing gallery remains |
| New / removed template | the create.js template branch (+ a *-template.js if large) + the "only N templates exist" list in EVERY per-agent rule file + the framework AGENTS.md/getting-started/README template matrix + the CLI --template validation + --help + test/scaffolds/* |
New control-flow throw or routing boundary file (notFound / redirect / forbidden / unauthorized and their not-found / forbidden / unauthorized / error / loading / global-error / global-not-found boundary files) | a runnable gallery demo that exercises it (a route that throws it plus the nearest boundary file), NOT just an app-tree bullet in the rule files + the home-page features array + test/scaffolds/* FEATURES/boundary-file asserts + generate + boot + hit the route. A doc bullet in AGENTS.md / CONVENTIONS.md is necessary but NOT sufficient: the gallery is the primary teaching surface, so an undemoed thrower is invisible to a scaffolding agent (the #848 gap). Carve-out: a root-only boundary (global-error / global-not-found) cannot mount under app/features/ without clashing with the generated app root, so teach those in the demo's PROSE rather than as a live route. |
New / renamed public @webjsdev/core or @webjsdev/server export, or a new routing convention file the router parses | test/scaffolds/gallery-coverage.json MUST classify it (a { demo } / { demoed: true }, or { exempt } with an internal: / deferred: reason) or the tier-2 CI gate (gallery-coverage.test.js) FAILS. Prefer a real demo; deferred: is a conscious, reviewer-visible exemption tracked for later. This is the coverage-gate teeth described above. |
| New convention/rule for generated apps | ALL per-agent rule files in lockstep (surface 3) + repo CONVENTIONS.md if the repo demonstrates it + agent-docs only if it also changes a framework API |
| Changed generated file (layout, theme, home, schema, middleware) | the generator (create.js/*-template.js) + any scaffold test asserting it + any doc/preview describing it + regenerate + boot |
New scaffold-shipped config/hook (.hooks/, webjs.* in the generated package.json, a check rule) | templates/** + webjs doctor/check that reads it + the per-agent rule files if agents must know it |
| Which templates ship the gallery (scoping) | the copyGallery / gallery gate in create.js + the "full-stack only / full-stack and saas" wording in the per-agent rule files AND the framework docs (grep the old scoping phrase everywhere) |
| Pure-internal CLI refactor (no change to generated output) | NONE. Record that no scaffold surface applies. |
Per-change sync procedure
Run the mandatory generate + boot + check verifications in PARALLEL when more than one template is affected: each verification is its own background Bash task, launched in one batch, with EVERY task's result collected before the sync is declared done (a forgotten background boot is a silently unverified template). Prefer the in-process harness (createRequestHandler + Request objects, the dogfood boot-check pattern in the start-work skill): it binds no port, so parallel runs cannot collide. When a real webjs dev listen is unavoidable, give each boot a distinct --port.
- Identify the change's IDENTIFYING TOKENS: the demo route (
app/features/<x>,app/api/features/<x>), the template name, the generated file path, the convention phrase, or the scoping phrase (e.g. "full-stack only"). - Grep those tokens across every scaffold surface:
git grep -n -iE '<token1>|<token2>' -- \ 'packages/cli/lib/**' 'packages/cli/templates/**' 'test/scaffolds/**' \ AGENTS.md README.md 'website/app/(site)/docs/**' - Update every surface the mapping says applies. For a SCOPING or wording change (e.g. "gallery is full-stack only" becoming "full-stack and saas"), the grep MUST surface and fix every copy, in the rule files AND the framework docs.
- VERIFY BY GENERATING (mandatory, non-negotiable). The generators emit
strings, so a template-literal / escaping / interpolation bug is invisible in
the generator's own syntax and only appears in the GENERATED app. For each
affected template, generate an app and prove it:
A scaffold change is NOT done until a freshly generated app of each affected template BOOTS, serves the new/changed route, passes# generate (files only is enough for structure/typecheck; install to boot) node -e "import('packages/cli/lib/create.js').then(m => m.scaffoldApp('probe', '/tmp/x', { template: 'full-stack', install: false }))" # then in the generated app: webjs check (clean), webjs typecheck (clean), # and boot it to hit the new route(s).webjs check, andwebjs typecheckis clean. - Run the scaffold tests (
node --test 'test/scaffolds/*.test.js') and add/adjust assertions (a new demo in the FEATURES list, a per-template inclusion/exclusion test, the counterfactual). - Respect the prose-punctuation invariant (#11) in every comment and doc, and
keep each demo densely commented (a header stating the webjs concept + the
why, and inline comments on the non-obvious idiom). Add a prune note where
removal is NOT obvious, which is what the demos that carry one do: a card
spanning several paths (the auth card names its route, its module, its api
routes and its schema column), or one that depends on another (the
server-actions card says to prune it with auth). A self-contained demo needs
none, since
npm run gallery:clearsheds the lot. The scaffold teaches by its comments, and a thin demo is a bug.
Audit-mode procedure (sweep the scaffold for drift)
Fan the sweep out like the doc-sync audit: one read-only Explore agent per surface of the map, spawned in one message; the agents report and the edits stay in the main session.
- List the shipped scaffold changes (new demos, new template, scoping changes, changed generated files).
- For each, pull its tokens and run the surface grep above.
- A surface is a GAP when the mapping says it applies but the token is absent or
describes stale behaviour there (a classic gap: a demo added to the full-stack
home but missing from the saas home, or a scoping phrase updated in one rule
file but not the other five).
- Skill-vs-gallery coverage sweep (the highest-value audit now that
gallery:clearstrips the gallery): for EACH gallery demo (app/features/<x>+ itsmodules/<x>), confirm the concept it teaches is also taught in.agents/skills/webjs/references/*.md. A concept the gallery demonstrates but the skill omits is a GAP, because it vanishes atgallery:clearand the agent building the real app never sees it. Fill it in the matching reference at the depth of its siblings.
- Skill-vs-gallery coverage sweep (the highest-value audit now that
- For a bulk audit, file a grounded follow-up via webjs-file-issue per gap
(title
scaffold: <surface> missing <thing>); for a single in-flight change, just fix all surfaces on the same PR.
What this skill does NOT do
- It does not regenerate
llms.txt/llms-full.txt(live-generated) or the website changelog (auto from PR titles). - It does not own framework API/behaviour docs (that is
webjs-doc-sync); when a change touches both a framework API and the scaffold, run both skills. - It does not decide whether a CLI change alters generated output; that judgement is step 1, and a pure-internal refactor correctly updates no scaffold surface.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

