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
There are two UI scaffolds that are largely the same: the default full-stack template and --template saas. The saas template is essentially the default (layout, gallery, db wiring) PLUS auth (login/signup, session, a protected dashboard, a User model). Maintaining a whole second template that is mostly a duplicate is drift-prone, and auth is a browsable concept a learner would reach for like any other feature.
Design / approach
Collapse to ONE UI template. Add a self-contained auth gallery feature card to the default template (a login / session / protected-route demo, prunable like every other card via gallery:clear), and remove the separate --template saas.
Decision rationale: this is the lean grow-in-place direction the scaffold already took (single-source skill, gallery:clear, post-#971). Auth-as-a-card teaches the concept without forcing a whole separate template.
DECIDED (owner): the auth card is NOT just a browsable demo, it WIRES A REAL PROTECTED ROUTE so a fresh default app keeps the saas "auth already wired in" baseline. So the card ships: a users table in db/schema.server.ts, createAuth() config, login/signup pages, session wiring, AND a genuinely protected route (a middleware.ts gate or a page-level auth() / unauthorized() check that redirects an anonymous visitor to login). Pruning it via gallery:clear removes the whole auth surface (card, modules, the users table, the protected route) back to the minimal base, the same way the demo todos table is dropped today. This gives one template that is minimal by default but carries a real, promotable auth baseline, replacing what --template saas did. Breaking change to webjs create --template saas, acceptable since WebJs has no users yet (no back-compat burden).
Implementation notes (for the implementing agent)
Where to edit:
Template handling + saas wiring: packages/cli/lib/create.js (template dispatch) and packages/cli/lib/saas-template.js (remove, or fold its auth pieces into the new gallery card). The --template flag + help text in packages/cli/bin/webjs.js (the create usage around L163, and the create handler around L878).
New gallery card: packages/cli/templates/gallery/app/features/auth/ + packages/cli/templates/gallery/modules/auth/ (login/session/protected demo). Register in the FEATURES array (create.js ~L1340).
gallery:clear: add the new auth module to the galleryModules list in packages/cli/templates/scripts/clear-gallery.mjs so the card is pruned like the rest. NOTE the current clear script has a comment about KEEPING saas auth modules; once saas is removed, reconcile that.
Tests: test/scaffolds/gallery-coverage.test.js generates all THREE templates today (['full-stack','api','saas'] around L185) plus scaffold-*.test.js; drop saas from those and add coverage for the auth card. The createAuth / Credentials / Google / GitHub server exports are demoed today only by the saas template, so they move into the coverage picture via the new card or need re-classification in test/scaffolds/gallery-coverage.json.
Docs: grep --template saas / saas across docs/, website/, README.md, AGENTS.md, and packages/cli/templates/** agent rule files and update every mention (invoke webjs-doc-sync + webjs-scaffold-sync).
Landmines: removing a template is a coordinated change across generator + tests + docs + coverage manifest; a stale saas reference will red the scaffold suites. The auth server exports MUST stay demonstrated somewhere or gallery-coverage.test.js fails. The gallery ships in every UI template; generators emit strings, so verify by generating + booting a fresh app.
Invariants: default to a real database (Drizzle + SQLite); server-only code behind .server.ts; PE-safe login form (a no-JS <form> posting to a page action or route). Light DOM + Tailwind.
Upgrade the server-actions greet demo's auth middleware (shipped in PR feat: add webjs-frame gallery demo and rework the server-actions demo #989, packages/cli/templates/gallery/modules/server-actions/middleware/require-auth.server.ts) to the real session: replace the signedOut-from-input hack with await getCurrentUser(ctx.request) reading the signed session cookie (which rides the same-origin RPC POST, so no wrapping segment middleware is needed), and drop the signedOut flag from greet.server.ts + the checkbox in components/greeter.ts. The ctx.context.user -> actionContext().user handoff and the 401 short-circuit are unchanged; only the identity source swaps, and the 401 becomes real (an anonymous caller is genuinely denied). The demo was deliberately shaped for this swap.
Consider bundling the smaller gallery gaps from the same audit as follow-ups or into this work: a lazy static lazy component demo, HTTP-verb action caching missing from the UI caching demo (app/features/caching/, taught only in the api template today), and no shipped readiness.ts template.
Acceptance criteria
The default template ships auth wired in: a users table, createAuth(), login/signup pages, session wiring, AND a genuinely protected route that redirects an anonymous visitor to login (an authenticated visitor reaches it)
gallery:clear removes the entire auth surface (card, modules, users table, protected route) back to the minimal base, verified by a fresh generate + clear + webjs check
--template saas is removed; webjs create offers one UI template (plus api)
The auth-related @webjsdev/server exports stay demonstrated (coverage manifest green)
All docs / agent rule files / README mentioning saas are updated
Scaffold suites updated (no saas generation) and green; generate + boot + webjs check on a fresh app pass
Problem
There are two UI scaffolds that are largely the same: the default full-stack template and
--template saas. The saas template is essentially the default (layout, gallery, db wiring) PLUS auth (login/signup, session, a protected dashboard, a User model). Maintaining a whole second template that is mostly a duplicate is drift-prone, and auth is a browsable concept a learner would reach for like any other feature.Design / approach
Collapse to ONE UI template. Add a self-contained
authgallery feature card to the default template (a login / session / protected-route demo, prunable like every other card viagallery:clear), and remove the separate--template saas.Decision rationale: this is the lean grow-in-place direction the scaffold already took (single-source skill,
gallery:clear, post-#971). Auth-as-a-card teaches the concept without forcing a whole separate template.DECIDED (owner): the auth card is NOT just a browsable demo, it WIRES A REAL PROTECTED ROUTE so a fresh default app keeps the saas "auth already wired in" baseline. So the card ships: a
userstable indb/schema.server.ts,createAuth()config, login/signup pages, session wiring, AND a genuinely protected route (amiddleware.tsgate or a page-levelauth()/unauthorized()check that redirects an anonymous visitor to login). Pruning it viagallery:clearremoves the whole auth surface (card, modules, theuserstable, the protected route) back to the minimal base, the same way the demotodostable is dropped today. This gives one template that is minimal by default but carries a real, promotable auth baseline, replacing what--template saasdid. Breaking change towebjs create --template saas, acceptable since WebJs has no users yet (no back-compat burden).Implementation notes (for the implementing agent)
packages/cli/lib/create.js(template dispatch) andpackages/cli/lib/saas-template.js(remove, or fold its auth pieces into the new gallery card). The--templateflag + help text inpackages/cli/bin/webjs.js(the create usage around L163, and the create handler around L878).packages/cli/templates/gallery/app/features/auth/+packages/cli/templates/gallery/modules/auth/(login/session/protected demo). Register in theFEATURESarray (create.js~L1340).gallery:clear: add the newauthmodule to thegalleryModuleslist inpackages/cli/templates/scripts/clear-gallery.mjsso the card is pruned like the rest. NOTE the current clear script has a comment about KEEPING saas auth modules; once saas is removed, reconcile that.test/scaffolds/gallery-coverage.test.jsgenerates all THREE templates today (['full-stack','api','saas']around L185) plusscaffold-*.test.js; drop saas from those and add coverage for the auth card. ThecreateAuth/Credentials/Google/GitHubserver exports are demoed today only by the saas template, so they move into the coverage picture via the new card or need re-classification intest/scaffolds/gallery-coverage.json.--template saas/saasacrossdocs/,website/,README.md,AGENTS.md, andpackages/cli/templates/**agent rule files and update every mention (invoke webjs-doc-sync + webjs-scaffold-sync).gallery-coverage.test.jsfails. The gallery ships in every UI template; generators emit strings, so verify by generating + booting a fresh app..server.ts; PE-safe login form (a no-JS<form>posting to a page action or route). Light DOM + Tailwind.packages/cli/templates/gallery/modules/server-actions/middleware/require-auth.server.ts) to the real session: replace thesignedOut-from-input hack withawait getCurrentUser(ctx.request)reading the signed session cookie (which rides the same-origin RPC POST, so no wrapping segment middleware is needed), and drop thesignedOutflag fromgreet.server.ts+ the checkbox incomponents/greeter.ts. Thectx.context.user->actionContext().userhandoff and the 401 short-circuit are unchanged; only the identity source swaps, and the 401 becomes real (an anonymous caller is genuinely denied). The demo was deliberately shaped for this swap.static lazycomponent demo, HTTP-verb action caching missing from the UI caching demo (app/features/caching/, taught only in the api template today), and no shippedreadiness.tstemplate.Acceptance criteria
userstable,createAuth(), login/signup pages, session wiring, AND a genuinely protected route that redirects an anonymous visitor to login (an authenticated visitor reaches it)gallery:clearremoves the entire auth surface (card, modules,userstable, protected route) back to the minimal base, verified by a fresh generate + clear +webjs check--template saasis removed;webjs createoffers one UI template (plusapi)@webjsdev/serverexports stay demonstrated (coverage manifest green)saasare updatedwebjs checkon a fresh app pass