Skip to content

Make the scaffold the primary how-to-use-webjs context vehicle for AI agents #821

Description

@vivek7405

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.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:

  1. 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.
  2. EXAMPLE CODE: concrete reference the agent studies, then replaces/prunes (dogfood: scaffold guidance should prune unused files/folders, not keep everything #818).

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:

  • app/page.ts with a TYPED import 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.
  • An interactive component demonstrating the factory WebComponent({ ... }) + prop + signals + the declarative optimistic() mutation idiom.
  • A '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.ts vs 'use server' distinction is shown, not just told (dogfood: make the .server.ts vs 'use server' distinction unmissable for agents #820).
  • A 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.
  • 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.

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 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)

Implementation notes (for the implementing agent)

  • 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.
  • Guidance makes explicit that the knowledge layer is always kept and pruning (dogfood: scaffold guidance should prune unused files/folders, not keep everything #818) removes only unused example code.
  • 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.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Fields

No fields configured for issues without a type.

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions