Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
9a92b23
chore: start auth gallery card work
vivek7405 Jul 22, 2026
187ca23
feat(scaffold): add auth gallery card (login, session, protected route)
vivek7405 Jul 22, 2026
03c90e4
feat(scaffold): fold auth into the UI template, drop the saas template
vivek7405 Jul 22, 2026
98dc49f
feat(scaffold): wire the server-actions greet demo to real session auth
vivek7405 Jul 22, 2026
647cb99
test(scaffold): retarget saas suites to the full-stack auth card
vivek7405 Jul 22, 2026
0d53e2a
docs: sync all surfaces for two templates (auth folded into full-stack)
vivek7405 Jul 22, 2026
0611c6e
docs: drop saas from CLI wrapper, package docs, and blog agent rules
vivek7405 Jul 22, 2026
d0ccc32
fix(scaffold): document auth-card coupling, drop stale saas references
vivek7405 Jul 22, 2026
8920c68
feat(scaffold): add a Back-to-Gallery link to the auth dashboard nav
vivek7405 Jul 22, 2026
3d56c64
feat(scaffold): add a shared features layout with a back-to-gallery link
vivek7405 Jul 22, 2026
c108866
test(scaffold): assert the shared features layout links back to the g…
vivek7405 Jul 22, 2026
756696e
feat(scaffold): add back-to-gallery link to example apps too
vivek7405 Jul 22, 2026
0877f0c
docs: use neutral 'ORM' in the website backend template card title
vivek7405 Jul 22, 2026
760644b
docs: drop Drizzle from the website backend card body (neutral framing)
vivek7405 Jul 22, 2026
a385f3d
docs(scaffold): explain frames vs layouts in the frames gallery demo
vivek7405 Jul 22, 2026
cf154f7
feat(scaffold): add a dedicated <webjs-stream> gallery card
vivek7405 Jul 22, 2026
20d3fdd
feat(scaffold): add gallery:clear to the api template (Closes #1041)
vivek7405 Jul 22, 2026
19c942a
docs: backend card title reads 'Route handlers + Database'
vivek7405 Jul 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .agents/skills/webjs/references/runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ The 103 Early Hints gap costs only a small first-load latency edge where an edge
webjs create my-app --runtime bun
```

`--runtime` is orthogonal to `--template`, so it re-flavors any of full-stack, saas, or api. A Bun scaffold emits a `bun.lock`, a pure `oven/bun:1` Dockerfile plus a bun-install CI, and bun-command agent docs. The test, db, and check tooling still runs on Node.
`--runtime` is orthogonal to `--template`, so it re-flavors either full-stack or api. A Bun scaffold emits a `bun.lock`, a pure `oven/bun:1` Dockerfile plus a bun-install CI, and bun-command agent docs. The test, db, and check tooling still runs on Node.

## Running on Bun

Expand Down
2 changes: 1 addition & 1 deletion .agents/skills/webjs/references/service-worker.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Read this when you want an offline experience or an asset cache in a WebJs app,

## What ships and why it is safe

WebJs's UI scaffolds (full-stack and saas, not the api template) ship a hand-authored service worker at `public/sw.js` and an offline fallback at `public/offline.html`. Both ship **dormant**: they do nothing until the app registers the worker, and the worker only ever registers from JavaScript. So with JS off no worker exists, and pages, links, and forms behave exactly as before. It is opt-in and adds an offline experience plus an asset cache without changing the no-JS baseline.
WebJs's UI scaffold (full-stack, not the api template) ships a hand-authored service worker at `public/sw.js` and an offline fallback at `public/offline.html`. Both ship **dormant**: they do nothing until the app registers the worker, and the worker only ever registers from JavaScript. So with JS off no worker exists, and pages, links, and forms behave exactly as before. It is opt-in and adds an offline experience plus an asset cache without changing the no-JS baseline.

This is a thin, hand-readable worker built directly on the native Service Worker and Cache Storage APIs. There is no Workbox, no precache framework, and no bundler step, matching WebJs's no-build, close-to-web-standards posture. The file is yours to edit, not a framework internal.

Expand Down
10 changes: 5 additions & 5 deletions .claude/skills/webjs-scaffold-sync/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ it applies, then update or consciously skip each.
1. **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 like `isApi` / `isSaas` / `!isApi`).
- `packages/cli/lib/saas-template.js` (the saas-only files: auth, login/signup,
dashboard, the saas schema).
- `packages/cli/lib/api-gallery.js` (the api backend-features showcase).
gates like `isApi` / `isFullStack` / `!isApi`).
- `packages/cli/lib/api-gallery.js` (the api backend-features showcase). Auth
is a full-stack GALLERY card now (`templates/gallery/{app/features/auth,
modules/auth}`), pruned by `gallery:clear`, not a separate template.
- Any future `*-template.js` / `*-gallery.js` split out for escaping sanity.
2. **The verbatim template files** copied into every app:
- `packages/cli/templates/gallery/**` (the UI feature gallery + example app,
Expand Down Expand Up @@ -144,7 +144,7 @@ it applies, then update or consciously skip each.
affected template, generate an app and prove it:
```sh
# 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: 'saas', install: false }))"
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 (only no-scaffold-placeholder should
# remain), webjs typecheck (clean), and boot it to hit the new route(s).
```
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/webjs-start-work/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ Doc drift is the #1 way a framework rots. Documentation MUST stay in sync with c
- `CLAUDE.md` (only if a Claude Code rule is specifically added; framework conventions go in AGENTS.md).
- `.github/*.md` (issue templates, PR templates, contributing) when a workflow rule shifts.
3. **User-facing docs site** under `docs/app/docs/<topic>/page.ts` (these are `.ts` files, not markdown, so they're excluded by the markdown query but they're the canonical user-facing reference). If the change is visible to a user reading the docs site, update the matching topic page. Add a new page if the surface is new and there's no obvious home.
4. **Scaffold templates** under `packages/cli/templates/` and the generators `packages/cli/lib/{create,saas-template}.js`. Update if the change affects what `webjs create` generates. The scaffold ships a gallery index home + layout + db wiring, a densely-commented feature gallery (`packages/cli/templates/gallery/**`, demos under `app/features/` plus `app/examples/todo`) and the api showcase (`api-gallery.js`), plus one cross-agent skill at `.agents/skills/webjs/` (SKILL.md + references) that the agent grows in place; there are no per-agent rule files. A feature change that agents should know about lands in the skill; a generated-code change lands in the generators, verified with `generate + boot + webjs check`.
4. **Scaffold templates** under `packages/cli/templates/` and the generators `packages/cli/lib/{create,api-gallery}.js`. Update if the change affects what `webjs create` generates. The scaffold ships a gallery index home + layout + db wiring, a densely-commented feature gallery (`packages/cli/templates/gallery/**`, demos under `app/features/` plus `app/examples/todo`) and the api showcase (`api-gallery.js`), plus one cross-agent skill at `.agents/skills/webjs/` (SKILL.md + references) that the agent grows in place; there are no per-agent rule files. A feature change that agents should know about lands in the skill; a generated-code change lands in the generators, verified with `generate + boot + webjs check`.
5. **The MCP server** (the standalone `@webjsdev/mcp` package, `packages/mcp/src/{mcp,mcp-docs,mcp-source}.js`, extracted from the CLI in #415; `webjs mcp` and `npx @webjsdev/mcp` both run it). The MCP is how AI agents learn and introspect webjs, so it must stay in lockstep with the surfaces it exposes. Update it whenever the change touches what it serves:
- **Introspection tools** (`list_routes` / `list_actions` / `list_components` / `check`): if you change the route table shape, the action/RPC-hash scheme, component registration, or a `webjs check` rule, update the matching tool projection so the MCP reports reality.
- **Knowledge layer** (resources + `init` + `docs` + prompts): the resources are the skill at `.agents/skills/webjs/` (SKILL.md + references/) + `AGENTS.md`, so a docs change is picked up automatically (it is bundled at `prepack`). But if you add or rename a skill reference file, ADD A NEW INVARIANT, change the execution model, or add an authoring concept an agent should know, also: (a) confirm the `init` primer still pulls the right `AGENTS.md` sections (it sources the Execution-model + Invariants headings, so a heading rename breaks it), and (b) add a guided-workflow PROMPT for any new common recipe (a new page/route/action/component-shaped task). New recipes without a prompt are a silent gap.
Expand Down
6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ Every code change MUST include, automatically:

1. **Tests, every applicable layer (not just unit).** Ship the tests that prove the change across EVERY layer it touches: **unit** (`packages/*/test/**`, `test/**`, including the counterfactual that fails when reverted), **browser** (`*/test/**/browser/*` via `npm run test:browser`, for hydration / DOM / slots / client router / custom-element upgrade), **e2e** (`test/e2e/*.test.mjs` via `WEBJS_E2E=1`, including network probes / navigation / streaming), and **smoke** (`test/examples/*/smoke/*`). A unit test is NECESSARY BUT NOT SUFFICIENT for any client-router / component / browser-facing change (the headline behaviour is a browser/e2e assertion). **Bun parity is part of the task, not an afterthought:** WebJs runs on Node 24+ AND Bun (#508), so a change to a runtime-sensitive surface (the serializer, the node:http vs `Bun.serve` listener + request path, SSR / action / CSRF dispatch, streams, `node:crypto`, the TS stripper, auth / session / cors) MUST be proven on Bun (`node scripts/run-bun-tests.js` + the touched `test/bun/*.mjs` under `bun`) AND ship an added/updated `test/bun/<feature>.mjs` cross-runtime assertion. `npm test` does NOT run browser, e2e, or Bun; run them yourself and report the result. Never report work done with failing or missing tests. See `references/testing.md`. Enforced by `.claude/hooks/require-tests-with-src.sh` (the scaffold variant WARNS unless `WEBJS_TEST_GATE=block`) and `.claude/hooks/require-bun-parity-with-runtime-src.sh` (BLOCKS a commit that stages runtime-sensitive source with no `test/bun/**` test; escape hatch `WEBJS_BUN_VERIFIED=1`).
2. **Documentation, part of the definition of done (not optional).** A task is NOT done until EVERY doc surface its change touches is in sync: `AGENTS.md` + the skill at `.agents/skills/webjs/` (SKILL.md + references/) for new API surface, `CONVENTIONS.md` (and per-package `AGENTS.md`) for new conventions, the docs site (`docs/app/docs/<topic>`), the marketing `website/`, the scaffold templates (`packages/cli/templates/` per-agent rule files), and `README.md` for a headline capability. Updating `AGENTS.md` alone reproduces the #488 gap (docs site left stale). Invoke the `webjs-doc-sync` skill to sync every applicable surface. Enforced by `.claude/hooks/require-docs-with-src.sh`, which BLOCKS a commit that stages public `packages/*/src` source with no doc surface alongside it (a genuinely internal refactor / CI / release / perf change with no behaviour change bypasses with `WEBJS_NO_DOC_GATE=1`).
3. **Scaffold + skill sync (when a feature changes what apps should do).** The scaffold `webjs create` emits is a gallery index home + a root layout + db wiring, a densely-commented feature gallery (`packages/cli/templates/gallery/**`, single-concept demos under `app/features/` plus the `app/examples/todo` app, shipped in every UI template) and the api backend-features showcase (`packages/cli/lib/api-gallery.js`), plus the one cross-agent skill at `packages/cli/templates/.agents/skills/webjs/` (SKILL.md + references). So when a WebJs feature is added or changed, ask: does the generator (`packages/cli/lib/{create,saas-template,api-gallery}.js`), a gallery demo (`packages/cli/templates/gallery/`), or the agent skill (`.agents/skills/webjs/SKILL.md` + its `references/`) need to move so a freshly scaffolded app and the skill teach the new reality? Verify by generating an app and running `generate + boot + webjs check` (the generators emit strings, so an escaping bug only shows in a freshly generated app). See `framework-dev.md`.
3. **Scaffold + skill sync (when a feature changes what apps should do).** The scaffold `webjs create` emits is a gallery index home + a root layout + db wiring, a densely-commented feature gallery (`packages/cli/templates/gallery/**`, single-concept demos under `app/features/` plus the `app/examples/todo` app, shipped in every UI template) and the api backend-features showcase (`packages/cli/lib/api-gallery.js`), plus the one cross-agent skill at `packages/cli/templates/.agents/skills/webjs/` (SKILL.md + references). So when a WebJs feature is added or changed, ask: does the generator (`packages/cli/lib/{create,api-gallery}.js`), a gallery demo (`packages/cli/templates/gallery/`), or the agent skill (`.agents/skills/webjs/SKILL.md` + its `references/`) need to move so a freshly scaffolded app and the skill teach the new reality? Verify by generating an app and running `generate + boot + webjs check` (the generators emit strings, so an escaping bug only shows in a freshly generated app). See `framework-dev.md`.
4. **Convention validation.** Run `webjs check` and fix violations.

### Git workflow (mandatory)
Expand Down Expand Up @@ -449,7 +449,7 @@ const result = await optimistic(liked, true, () => likePost(postId));

## Scaffolding

Three scaffolds exist (do not invent template names): `webjs create <name>` (full-stack: layout, page, components, modules, Drizzle+SQLite), `webjs create <name> --template api` (backend-only routes + modules + Drizzle, no SSR), `webjs create <name> --template saas` (auth + login/signup + protected dashboard + User model). The `--db sqlite|postgres` flag (default sqlite) picks the dialect; the schema/queries/actions are identical across dialects (see #563). The `--runtime node|bun` flag (default node, #541) is ORTHOGONAL to the template and re-flavors any of the three for Bun (`bun --bun` dev/start scripts so the SERVER runs on Bun, `bun.lock`, a pure `oven/bun:1` Dockerfile (#595; safe since cli@0.10.20's npx-free `webjs db migrate` (#570) needs no Node in the image) + bun-install CI, bun-command agent docs; the test/db/check tooling stays on Node); `bun create webjs <name>` auto-detects it. Pick from the request: default for any product with UI (todo, blog, dashboard, marketplace, social, e-commerce), `api` for an HTTP/JSON API with no UI, `saas` for accounts/login/signup; default to full-stack when ambiguous.
Two scaffolds exist (do not invent template names): `webjs create <name>` (full-stack: layout, page, components, modules, Drizzle+SQLite, plus a browsable feature gallery), and `webjs create <name> --template api` (backend-only routes + modules + Drizzle, no SSR). Auth is one of the full-stack gallery cards (login + a signed session + a real protected route), so a full-stack app already carries a promotable auth baseline (this replaced the former `--template saas`). The `--db sqlite|postgres` flag (default sqlite) picks the dialect; the schema/queries/actions are identical across dialects (see #563). The `--runtime node|bun` flag (default node, #541) is ORTHOGONAL to the template and re-flavors either for Bun (`bun --bun` dev/start scripts so the SERVER runs on Bun, `bun.lock`, a pure `oven/bun:1` Dockerfile (#595; safe since cli@0.10.20's npx-free `webjs db migrate` (#570) needs no Node in the image) + bun-install CI, bun-command agent docs; the test/db/check tooling stays on Node); `bun create webjs <name>` auto-detects it. Pick from the request: default (full-stack) for any product with UI (todo, blog, dashboard, marketplace, social, e-commerce, a SaaS with accounts/login), `api` for an HTTP/JSON API with no UI; default to full-stack when ambiguous.

Rules: **always scaffold via `webjs create`** (never hand-roll). **Default to a real database (Drizzle + SQLite); NEVER use JSON files, in-memory arrays, or localStorage for persistence.** Update `db/schema.server.ts` to real models FIRST, then `webjs db generate` + `webjs db migrate`, then build pages/actions/queries. **The scaffold ships a gallery index home, a neutral-palette root layout, db wiring, and a densely-commented feature gallery** (single-concept demos under `app/features/` plus the `app/examples/todo` app, with logic in `modules/`), alongside the one cross-agent skill at `.agents/skills/webjs/` (a routing `SKILL.md` + on-demand `references/`) that teaches how to build. Treat the gallery as browsable reference: read the demos to learn the idioms, then build the app the user asked for by growing the scaffold (add routes under `app/`, components under `components/`, features under `modules/<feature>/`, keep server-only code behind `.server.ts`) and prune the demos the app does not use (delete the `app/features/<x>` route AND its `modules/<x>`). Give a UI app its own palette by setting the token values in `app/layout.ts`. There is no design gate and no placeholder gate: taste is the agent's job, not the checker's. Docs at https://docs.webjs.dev.

Expand All @@ -469,7 +469,7 @@ webjs types # generate .webjs/routes.d.ts (typed Route un
webjs version # print the installed @webjsdev/cli version (also: webjs --version / -v, #975)
webjs help [command] # full usage banner, or per-command usage + Options + Examples (e.g. webjs help routes, #975). Flag forms: webjs --help / -h (banner), webjs <command> --help / -h (that command). typecheck/db/ui --help forward to their wrapped tool; an unknown topic exits 1
webjs typecheck [tsc args...] # the project's own tsc --noEmit
webjs create <name> [--template api|saas]
webjs create <name> [--template api]
webjs db <generate|migrate|push|studio|seed> # wraps drizzle-kit (+ runs db/seed.server.ts)
webjs ui init | add <names...> | list | view <name>
webjs vendor pin|unpin|list|audit|outdated|update [--from PROVIDER] # importmap pinning, .webjs/vendor/importmap.json
Expand Down
23 changes: 12 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,19 @@ TypeScript with zero build step, real SSR with Declarative Shadow DOM.

## Quickstart

> **AI agents, read this before scaffolding.** Only three templates exist
> (`full-stack` default, `--template api`, `--template saas`), and the CLI
> rejects anything else. Always start from one of them. Never hand-roll
> the directory structure. Default to **full-stack with Drizzle + SQLite**.
> Never store app data in JSON files, in-memory arrays, or localStorage
> as a substitute for the database. The scaffold is **reference only**.
> **AI agents, read this before scaffolding.** Only two templates exist
> (`full-stack` default, `--template api`), and the CLI rejects anything
> else. Always start from one of them. Never hand-roll the directory
> structure. Default to **full-stack with Drizzle + SQLite**. Never store
> app data in JSON files, in-memory arrays, or localStorage as a
> substitute for the database. The scaffold is **reference only**.
> Replace the example layout, page, components, and `User` model with
> the app the user actually asked for. Picker:
>
> - Any product UI (todo, blog, notes, dashboard, marketplace, social, e-commerce…) → **default** (`webjs create <name>`)
> - Any product UI (todo, blog, notes, dashboard, marketplace, social, e-commerce, a SaaS with accounts…) → **default** (`webjs create <name>`)
> - Backend-only HTTP/JSON API, no UI → **`--template api`**
> - Auth, login/signup, protected dashboard, SaaS → **`--template saas`**
>
> Auth is one of the full-stack gallery cards (login, a signed session, and a real protected route), so a default app already carries a promotable auth baseline.
>
> **The scaffold is a starting point, grown in place.** It ships a gallery index home, a neutral-palette root layout, database wiring, and a densely-commented feature gallery (single-concept demos under `app/features/` plus the `app/examples/todo` app, with logic in `modules/`). The framework context ships as one cross-agent skill, `.agents/skills/webjs/SKILL.md` (a routing skill), alongside `AGENTS.md` and `.agents/rules/workflow.md`. Read the skill and browse the gallery, then build the app the user asked for on top of the scaffold, pruning the demos it does not use.
>
Expand All @@ -56,11 +57,11 @@ npm create webjs@latest my-app # full-stack (pages + API + components + Drizzl
cd my-app && npm run dev
# → http://localhost:8080

# Backend-only API
# Backend-only API (routes + modules + Drizzle, no UI)
npm create webjs@latest my-api -- --template api

# SaaS starter (auth + dashboard + Drizzle)
npm create webjs@latest my-saas -- --template saas
# Auth (login/signup, session, a protected route) ships as a gallery card
# in the default full-stack app. No separate template needed.

# Prefer Bun? webjs runs on Node 24+ or Bun. Add --runtime bun to any
# template (it is orthogonal to --template), or scaffold through Bun and
Expand Down
Loading
Loading