You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The scaffold is the single highest-leverage place to teach an AI agent HOW to use webjs, because it is loaded into the agent's working directory before any code is written. Today it teaches through prose (AGENTS.md / CONVENTIONS.md / per-agent rule files / the MCP) plus a thin example (a "Hello from" page + example User model, and a users/auth module only in api/saas). That under-uses the scaffold as a teaching vehicle: the example code does not demonstrate the core idioms an agent must get right (typed metadata, the .server.ts vs 'use server' distinction, signals + optimistic() mutations, the modules architecture, a route.ts, a no-JS PE form, light-DOM + Tailwind), so the agent has to reconstruct them from prose, which is exactly where the first-pass friction shows up (see #817, #820).
The scaffold delivers context in two layers that must be treated distinctly:
DURABLE KNOWLEDGE (AGENTS.md, CONVENTIONS.md, per-agent rule files, the MCP): read before/while building, always KEPT (never pruned), so it stays as context for every future iteration on the app.
Maximizing layer 1 and shipping a curated, heavily-commented layer 2 gives the agent maximum context; #818 then prunes only the unused example CODE from the DELIVERED app, without removing the knowledge. The two are complementary.
Design / approach
Ship a curated, heavily-commented "teaching set" of examples that demonstrates the full core surface, each example annotated with the WHY and the invariant it respects, and each carrying the webjs-scaffold-placeholder marker so the agent replaces/prunes it after learning from it (so webjs check still forces replacement, and #818 prunes the unused rest). Cover, per template as appropriate:
A route.ts HTTP handler example, and a no-JS PE <form> + page action example.
Styling: light DOM + Tailwind with the design tokens.
Per template: full-stack gets the full teaching set; api gets the API-relevant subset (routes, actions, queries, modules; no UI); saas builds on full-stack + the auth slice. Also review the durable knowledge surfaces (AGENTS.md / CONVENTIONS.md / per-agent files / MCP prompts) for completeness as the primary teaching vehicle.
Comment standard: teach in the comments (the comments ARE the context)
The examples must be DENSELY commented, because the comments are the primary teaching payload, not the code. Do not just show usage; annotate every non-obvious decision inline. Each demonstrated pattern gets a comment that states four things: (1) WHAT it is, (2) WHY / the philosophy, (3) WHEN to use it AND when NOT to (the "where feasible, not where it hurts" shape), and (4) the invariant / doc it respects. Use MANY such comments across the teaching set, at each real decision point.
Concrete shapes (illustrative, not exhaustive):
Next to optimistic(...): // Optimistic UI: update instantly and roll back on failure. Use it where the client can PREDICT the result (todos, toggles, likes, reorders). Do NOT use it where it hurts: unpredictable/server-computed results, side-effectful or OAuth/payment mutations, or destructive-irreversible actions (confirm-first instead).
Next to a 'use server' action vs a no-directive .server.ts: // 'use server' = RPC-callable from the client. A .server.ts WITHOUT it is a server-only utility (throws if imported into a page/component); reach it via an action / route.ts / middleware.
Next to <label for=...>: // Associate clickable text with its control so a text click activates it (and screen readers announce it). Works on the JS path AND the no-JS form-submit path.
Next to import type { Metadata } from '@webjsdev/core': // Metadata is a @webjsdev/core type (NOT @webjsdev/server, where ActionResult lives). import type so the stripper erases it.
Next to a page's component tags: // Pages run server-only and do NOT hydrate: compose component tags for interactivity; an @click in page markup is dropped at SSR.
Next to a light-DOM + Tailwind block: // Light DOM + Tailwind by default; classes apply globally. Custom CSS in light DOM must be tag-prefixed (invariant 7).
The bar: an agent reading ONLY the scaffold's example files should learn the idiom AND its guardrails from the comments, without needing to open the docs. Density is a feature here (this is a teaching artifact, marker-gated and pruned after, #818), not the usual "code should be self-documenting" minimalism.
Design tension to resolve (name it in the implementation)
More example code = more context BUT more to prune (#818) and more scaffold-look to avoid mimicking (#815, merged). Resolution: the teaching examples are (a) tightly curated, (b) heavily commented so the VALUE is the explanation not the code, (c) webjs-scaffold-placeholder-gated so they are replaced/pruned, and (d) paired with the durable knowledge layer that is never pruned. The examples teach; the docs persist; #818 prunes the unused remainder AFTER the agent has learned from them.
We KEEP the three scaffolds (full-stack, api, saas) and enrich each, rather than consolidating to two (saas-as-default). The default full-stack stays auth-free but becomes the rich teaching example; saas stays as the concrete wired auth reference. Rationale + the auth-context analysis are in the closed research record #822.
Auth context (folded in from the template-strategy analysis)
Auth context is DURABLE and independent of the saas scaffold (verified): agent-docs/built-ins.md has "## Authentication (NextAuth-style)" + "## Sessions", the docs site has auth pages, and @webjsdev/server/src/auth.js is greppable. So a full-stack (no-auth) agent that later needs auth already has enough context. To make "add auth later" maximally reliable (first-pass), close these gaps as part of this work:
Add a dedicated auth recipe to agent-docs/recipes.md (today only the built-ins.md reference section exists, no step-by-step recipe).
Add an MCP add_auth guided prompt to PROMPT_BODIES in packages/mcp/src/mcp-docs.js (there are add_page / add_server_action / add_module, but none for auth).
Reconcile the two docs-site auth pages (/docs/auth and /docs/authentication) to one canonical page (a redirect from the other).
Keep saas as the concrete working auth example (the "need a full wired reference" case).
Relationship to existing issues (coordinate, do not duplicate)
Examples are generated inline in packages/cli/lib/create.js (page ~L1134, layout ~L931, api module ~L787-858); extend those with the teaching set per template. Keep the webjs-scaffold-placeholder markers so a fresh scaffold still fails webjs check until replaced, and passes webjs typecheck.
Sync the prose surfaces in lockstep (root + scaffold AGENTS.md, CONVENTIONS.md, .cursorrules, .github/copilot-instructions.md, .agents/rules/workflow.md) and the MCP PROMPT_BODIES in packages/mcp/src/mcp-docs.js.
Tests: test/scaffolds/* + packages/cli/test/* (a fresh scaffold of each template passes webjs check after placeholder removal, and webjs typecheck); a counterfactual that the placeholder markers still fire.
Invariant 11 (prose punctuation) applies to every comment/doc edit.
Acceptance criteria
Each template ships a curated, heavily-commented teaching set covering the core surface (page + typed metadata, layout, interactive component with signals + optimistic, 'use server' action + server-only query with the boundary comment, a module slice, a route.ts, a PE form), each webjs-scaffold-placeholder-marked.
The durable knowledge surfaces (AGENTS.md / CONVENTIONS.md / per-agent files / MCP) are reviewed and complete as the primary teaching vehicle.
A fresh scaffold of each template passes webjs check after markers are addressed, and passes webjs typecheck.
Every demonstrated pattern carries a dense inline comment stating what/why/when-to-use/when-NOT-to + the invariant (per the Comment standard), so an agent reading only the example files learns the idiom AND its guardrails.
Auth context is strengthened for the no-auth default: an auth recipe in agent-docs/recipes.md, an MCP add_auth prompt, the two docs auth pages reconciled, and saas kept as the concrete wired reference.
Problem / thesis
The scaffold is the single highest-leverage place to teach an AI agent HOW to use webjs, because it is loaded into the agent's working directory before any code is written. Today it teaches through prose (AGENTS.md / CONVENTIONS.md / per-agent rule files / the MCP) plus a thin example (a "Hello from" page + example User model, and a users/auth module only in api/saas). That under-uses the scaffold as a teaching vehicle: the example code does not demonstrate the core idioms an agent must get right (typed metadata, the
.server.tsvs'use server'distinction, signals +optimistic()mutations, the modules architecture, aroute.ts, a no-JS PE form, light-DOM + Tailwind), so the agent has to reconstruct them from prose, which is exactly where the first-pass friction shows up (see #817, #820).The scaffold delivers context in two layers that must be treated distinctly:
AGENTS.md,CONVENTIONS.md, per-agent rule files, the MCP): read before/while building, always KEPT (never pruned), so it stays as context for every future iteration on the app.Maximizing layer 1 and shipping a curated, heavily-commented layer 2 gives the agent maximum context; #818 then prunes only the unused example CODE from the DELIVERED app, without removing the knowledge. The two are complementary.
Design / approach
Ship a curated, heavily-commented "teaching set" of examples that demonstrates the full core surface, each example annotated with the WHY and the invariant it respects, and each carrying the
webjs-scaffold-placeholdermarker so the agent replaces/prunes it after learning from it (sowebjs checkstill forces replacement, and #818 prunes the unused rest). Cover, per template as appropriate:app/page.tswith a TYPEDimport type { Metadata } from '@webjsdev/core'+export const metadata: Metadata(dogfood: close first-pass friction found building a full-stack app #817), plus a comment on pages running server-only, not hydrating, and composing component tags.app/layout.ts(root shell, design tokens, PE), commented as infrastructure to keep and restyle.WebComponent({ ... })+prop+ signals + the declarativeoptimistic()mutation idiom.'use server'action WITH verb config AND a server-only query WITH the "server-only, no directive, do not import into a page/component" comment, so the.server.tsvs'use server'distinction is shown, not just told (dogfood: make the .server.ts vs 'use server' distinction unmissable for agents #820).modules/<feature>/slice (actions/queries/components/types) wired into the page, so the modules architecture is concrete in the full-stack default too (dogfood: close first-pass friction found building a full-stack app #817), not only api/saas.route.tsHTTP handler example, and a no-JS PE<form>+ pageactionexample.Per template: full-stack gets the full teaching set;
apigets the API-relevant subset (routes, actions, queries, modules; no UI);saasbuilds on full-stack + the auth slice. Also review the durable knowledge surfaces (AGENTS.md / CONVENTIONS.md / per-agent files / MCP prompts) for completeness as the primary teaching vehicle.Comment standard: teach in the comments (the comments ARE the context)
The examples must be DENSELY commented, because the comments are the primary teaching payload, not the code. Do not just show usage; annotate every non-obvious decision inline. Each demonstrated pattern gets a comment that states four things: (1) WHAT it is, (2) WHY / the philosophy, (3) WHEN to use it AND when NOT to (the "where feasible, not where it hurts" shape), and (4) the invariant / doc it respects. Use MANY such comments across the teaching set, at each real decision point.
Concrete shapes (illustrative, not exhaustive):
optimistic(...):// Optimistic UI: update instantly and roll back on failure. Use it where the client can PREDICT the result (todos, toggles, likes, reorders). Do NOT use it where it hurts: unpredictable/server-computed results, side-effectful or OAuth/payment mutations, or destructive-irreversible actions (confirm-first instead).'use server'action vs a no-directive.server.ts:// 'use server' = RPC-callable from the client. A .server.ts WITHOUT it is a server-only utility (throws if imported into a page/component); reach it via an action / route.ts / middleware.<label for=...>:// Associate clickable text with its control so a text click activates it (and screen readers announce it). Works on the JS path AND the no-JS form-submit path.import type { Metadata } from '@webjsdev/core':// Metadata is a @webjsdev/core type (NOT @webjsdev/server, where ActionResult lives). import type so the stripper erases it.// Pages run server-only and do NOT hydrate: compose component tags for interactivity; an @click in page markup is dropped at SSR.// Light DOM + Tailwind by default; classes apply globally. Custom CSS in light DOM must be tag-prefixed (invariant 7).The bar: an agent reading ONLY the scaffold's example files should learn the idiom AND its guardrails from the comments, without needing to open the docs. Density is a feature here (this is a teaching artifact, marker-gated and pruned after, #818), not the usual "code should be self-documenting" minimalism.
Design tension to resolve (name it in the implementation)
More example code = more context BUT more to prune (#818) and more scaffold-look to avoid mimicking (#815, merged). Resolution: the teaching examples are (a) tightly curated, (b) heavily commented so the VALUE is the explanation not the code, (c)
webjs-scaffold-placeholder-gated so they are replaced/pruned, and (d) paired with the durable knowledge layer that is never pruned. The examples teach; the docs persist; #818 prunes the unused remainder AFTER the agent has learned from them.Decision context (research #822)
We KEEP the three scaffolds (
full-stack,api,saas) and enrich each, rather than consolidating to two (saas-as-default). The defaultfull-stackstays auth-free but becomes the rich teaching example;saasstays as the concrete wired auth reference. Rationale + the auth-context analysis are in the closed research record #822.Auth context (folded in from the template-strategy analysis)
Auth context is DURABLE and independent of the saas scaffold (verified):
agent-docs/built-ins.mdhas "## Authentication (NextAuth-style)" + "## Sessions", the docs site has auth pages, and@webjsdev/server/src/auth.jsis greppable. So afull-stack(no-auth) agent that later needs auth already has enough context. To make "add auth later" maximally reliable (first-pass), close these gaps as part of this work:agent-docs/recipes.md(today only thebuilt-ins.mdreference section exists, no step-by-step recipe).add_authguided prompt toPROMPT_BODIESinpackages/mcp/src/mcp-docs.js(there areadd_page/add_server_action/add_module, but none for auth)./docs/authand/docs/authentication) to one canonical page (a redirect from the other).saasas the concrete working auth example (the "need a full wired reference" case).Relationship to existing issues (coordinate, do not duplicate)
Metadata+ Drizzle read pattern + MCP prompts) is a concrete SLICE of this; fold it in or implement first..server.tsvs'use server'distinction unmissable) is the teaching slice for the server boundary.Implementation notes (for the implementing agent)
packages/cli/lib/create.js(page ~L1134, layout ~L931, api module ~L787-858); extend those with the teaching set per template. Keep thewebjs-scaffold-placeholdermarkers so a fresh scaffold still failswebjs checkuntil replaced, and passeswebjs typecheck.AGENTS.md,CONVENTIONS.md,.cursorrules,.github/copilot-instructions.md,.agents/rules/workflow.md) and the MCPPROMPT_BODIESinpackages/mcp/src/mcp-docs.js.test/scaffolds/*+packages/cli/test/*(a fresh scaffold of each template passeswebjs checkafter placeholder removal, andwebjs typecheck); a counterfactual that the placeholder markers still fire.Acceptance criteria
'use server'action + server-only query with the boundary comment, a module slice, aroute.ts, a PE form), eachwebjs-scaffold-placeholder-marked.webjs checkafter markers are addressed, and passeswebjs typecheck.agent-docs/recipes.md, an MCPadd_authprompt, the two docs auth pages reconciled, andsaaskept as the concrete wired reference.