Skip to content

feat: fold auth into the default template as a gallery card, drop saas#1040

Merged
vivek7405 merged 18 commits into
mainfrom
feat/auth-gallery-card
Jul 22, 2026
Merged

feat: fold auth into the default template as a gallery card, drop saas#1040
vivek7405 merged 18 commits into
mainfrom
feat/auth-gallery-card

Conversation

@vivek7405

@vivek7405 vivek7405 commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Closes #993
Closes #1041

Summary

Collapse the two UI scaffolds into one. Auth becomes a self-contained gallery card in the default full-stack template, and the separate --template saas is removed. A fresh full-stack app carries a real, promotable auth baseline (a users table with passwordHash, createAuth(), login/signup, a signed session, and a genuinely protected route), and gallery:clear strips the whole auth surface back to the minimal base.

The PR also bundles a set of related scaffold-polish items surfaced while reviewing the generated apps (see "Bundled scaffold improvements").

Core change (#993)

  • Auth gallery card at packages/cli/templates/gallery/app/features/auth/ (login, signup, a protected dashboard/ subtree gated by middleware.ts) plus modules/auth/ (createAuth config, scrypt hashing, signup action, current-user query) plus app/api/auth/[...path]/route.ts (stays at the app root because createAuth hardcodes /api/auth/*) plus test/auth/auth.test.ts. Styled in plain Tailwind like every other card.
  • Generator: drop isSaas, add passwordHash to the UI users table, ship test/ from the gallery, register the Auth card, remove the homeAuthLinks splice and the writeSaasFiles call. Deleted saas-template.js and the orphaned lean-copy.js.
  • CLI: TEMPLATES and all usage/help/error text drop saas (webjs.js plus the create-webjs wrapper).
  • server-actions greet demo: reads the real session via getCurrentUser(ctx.request) instead of the signedOut simulation; the 401 is real.
  • gallery:clear prunes the whole auth surface plus the passwordHash column back to the exact minimal base.
  • Docs: AGENTS.md, README, docs site, website (3 template cards to 2, API card renamed to a clear "Backend" title), skill references, cli/ui package docs, blog agent rules.

Bundled scaffold improvements (same PR)

  • gallery:clear for the api template (Closes Add gallery:clear to the api template to shed its backend-features showcase #1041): clear-api-gallery.mjs sheds the backend-features showcase (app/api/features, modules/widgets, env.ts, the widgets test) and strips the features: block from the root route.ts, keeping the health + users baseline. Both templates now reset in one command.
  • Back-to-gallery navigation: a shared app/features/layout.ts and app/examples/layout.ts give every feature card, the auth pages, the dashboard, and the todo example a ← Gallery link (no per-page edits; gallery:clear removes them with their trees).
  • Dedicated <webjs-stream> card at app/features/stream plus modules/stream (element-level surgical DOM updates, Add a stream-action protocol with HTTP and live-channel delivery #248), previously only demoed as a button inside the WebSockets card.
  • Frames-vs-layouts explanation added to the frames demo.
  • Website neutrality: the backend card reads "Route handlers + ORM" and "a database" (defaults-not-lock-in framing).

Test plan

  • Scaffold suites: test/scaffolds/* 45/45, packages/cli/test/** 28/28, test/service-worker/* 12/12, ui registry 18/18, scaffold-strip 2/2.
  • Full-stack app: webjs check plus typecheck clean; boots (home, /features/auth, login, signup 200; dashboard 302 to login; then 200 "Welcome" after a real signup). Migrated DB: auth.test.ts 2/2, greet.test.ts 4/4. The <webjs-stream> card verified live in a real browser (append / prepend / replace / remove / self-remove all apply; 0 stray elements).
  • api app: webjs check plus typecheck clean; gallery:clear sheds the showcase, the cleared app boots (health/users 200, removed route 404) and passes webjs check.
  • gallery:clear (full-stack): full reset, schema reverted, boots 200, check clean; removes the features plus examples layouts too.
  • Bun (1.3.14): generated a --runtime bun full-stack app and ran the whole auth flow ON Bun (scrypt, bun:sqlite, createAuth session), the gallery layouts, and gallery:clear under bun, all green.
  • Dogfood: website / docs / ui-website boot 200 in prod mode.

Doc surfaces

  • AGENTS.md, README, docs site, website, skill references, cli/ui READMEs plus AGENTS, blog agent rules: Updated.
  • Scaffold (generators plus gallery plus both clear scripts plus tests): Updated, generate + boot + check verified for both templates.
  • MCP / editor plugins: N/A (no template list, grammar, or language-service surface changed).
  • Version bumps: N/A here (surface debt assessed separately after merge).

@vivek7405 vivek7405 self-assigned this Jul 22, 2026
@vivek7405

Copy link
Copy Markdown
Collaborator Author

Design: where the folded-in auth surface lives, and why

A few decisions worth writing down before the diff lands, since the issue left the layout open.

Auth is a gallery card under app/features/auth/, not root routes. login, signup, and the protected dashboard all live under app/features/auth/ (/features/auth/login, /features/auth/signup, /features/auth/dashboard), matching every other gallery card. This is the lean grow-in-place model: auth is browsable reference you promote by moving it, and gallery:clear prunes it through the existing app/features removal. The one exception is app/api/auth/[...path]/route.ts, which MUST stay at root: createAuth hardcodes /api/auth/signin/* and /api/auth/callback/* (auth.js L327/L350/L414), so the handler route cannot move under the feature folder. The login form still posts to /api/auth/signin/credentials; only the pages moved.

createAuth config + password hashing live in modules/auth/, not lib/. copyGallery copies only app/ and modules/, so putting auth.server.ts (the createAuth config) and password.server.ts in modules/auth/ makes them copy and prune with the card for free, no new copy plumbing and no lib/ merge against the ui-bootstrap lib/utils/.

Schema: users keeps settings and gains passwordHash. The inline generator adds passwordHash to the UI template's users table (not api). I kept the existing settings column so that after gallery:clear strips the passwordHash line, the minimal base schema is byte-identical to today's. So auth is purely additive over the current base, and clearing reverts it exactly.

The server-actions greet demo now does real auth. Per the issue, require-auth.server.ts swaps the signedOut-from-input simulation for getCurrentUser(ctx.request) reading the signed session cookie (the RPC POST is same-origin so the cookie rides along). The 401 becomes real: an anonymous caller is genuinely denied, and the greeter loses its "simulate signed-out" checkbox in favor of a real sign-in link. This couples the server-actions card to the auth card, which is fine since gallery:clear removes both.

The saas template was the default UI template plus auth. Collapse to one UI
template by shipping auth as a gallery card (app/features/auth + modules/auth +
app/api/auth), styled in plain Tailwind like every other card, and remove
--template saas and saas-template.js. The users table gains a passwordHash column
in the UI template; gallery:clear strips it (and the auth card) back to the
minimal base.
Replace the signedOut-from-input simulation in require-auth.server.ts with
getCurrentUser(ctx.request) reading the signed session cookie (the RPC POST is
same-origin so it rides along). The 401 is now real: an anonymous caller is
genuinely denied. Drop the signedOut flag from greet.server.ts and the simulate
checkbox from greeter.ts, and update greet.test.ts to prove denial + an
authenticated success path via a real login.
Drop saas from the template lists (gallery-coverage, runtime, template
validation), retarget the auth + dashboard + current-user assertions to the
full-stack auth card's new paths (app/features/auth, modules/auth), and delete
the obsolete saas ui-hygiene test plus the now-orphaned lean-copy.js helper.
@vivek7405
vivek7405 force-pushed the feat/auth-gallery-card branch from 05b715f to 647cb99 Compare July 22, 2026 07:09
Update AGENTS.md, README, the docs site (getting-started, ai-first, auth, cache),
the website templates section (3 cards to 2, rename the API card to a clear
Backend title noting it ships Drizzle + a backend gallery), and the skill
references. Auth is now presented as a full-stack gallery card, not a separate
--template saas.
Remove the saas template from the create-webjs wrapper's TEMPLATES + usage, the
cli/ui package docs, the blog's agent rule files + CONVENTIONS, the scaffold-sync
skill, and the scaffold-strip test's template matrix. Auth is a full-stack
gallery card now.
Address self-review: note the server-actions greet demo's dependency on the auth
card (at the import site and on the card page), fix the 'three templates' count
in the CLI help banner + comment, drop the dead lean-copy re-export from ui
registry/extract.js, and correct the saas-template.js path in the start-work
skill.

@vivek7405 vivek7405 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Went through the whole diff with a focus on the gallery:clear regex, the auth-card wiring, and any stale saas leftovers. The core is solid: the passwordHash strip regex matches exactly what the generator writes and no-ops on the api schema, the protected-route gate + createAuth paths are consistent, and invariant 1 holds (no server-only util reaches a browser-shipping page). Five things worth fixing, all now addressed in d0ccc327: the server-actions demo's new hard dependency on the auth card was undocumented at its own surface; the CLI help still said 'three templates'; and a few stale references (the deleted lean-copy re-export, the start-work skill's saas-template path) survived the sweep.

Comment thread packages/cli/bin/webjs.js

@vivek7405 vivek7405 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Second pass, narrowed to the risky edges: the gallery:clear + regenerate round-trip (the passwordHash/todos strip produces a valid schema; the leftover uuidPk/bool imports are unused but harmless and pre-date this PR), the unbunified static auth tests (node:test/assert/crypto only, all Bun-fine), the counterfactual strength of the retargeted scaffold assertions, app/api ownership vs clear, and the nullable passwordHash typing. All hold. Clean.

@vivek7405
vivek7405 marked this pull request as ready for review July 22, 2026 07:35
Every gallery feature demo under /features/* now gets a slim '← Gallery' link via
a shared app/features/layout.ts, so no card is a dead end. Drops the now-duplicate
link from the auth dashboard sub-nav (the features layout provides it).
Mirror the features layout with app/examples/layout.ts so the todo example (and
any future example app) gets the same '← Gallery' link. gallery:clear removes it
with the app/examples tree.
renderStream() / <webjs-stream> (element-level surgical DOM updates, #248) was
only demoed as a secondary button inside the WebSockets card. Add a dedicated
card at app/features/stream + modules/stream showing append / prepend / replace /
remove / update by target id, registered in FEATURES, pruned by gallery:clear,
and covered by the scaffold tests.
The api template now ships its own gallery:clear (clear-api-gallery.mjs) so its
backend-features showcase can be shed in one command, matching the full-stack
gallery reset. It removes app/api/features, modules/widgets, env.ts, and the
widgets test, and strips the features block from the root app/route.ts, keeping
the health + users baseline. Covered by a scaffold test (with a counterfactual on
the route reset) and noted in the getting-started docs.

@vivek7405 vivek7405 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the additions on top of the auth work: the card, the api-template gallery:clear, and the shared back-to-gallery layouts. The renderStream payloads are well-formed and the plain-field (non-signal) counter correctly keeps render() from reconciling the surgical DOM mutations away; the api features-strip regex matches only the features block's own closer against the real generated route.ts (endpoints stays valid TS) and the removal set matches exactly what api-gallery emits; the nested layouts wrap cleanly with one back-link above the dashboard sub-nav. Clean.

@vivek7405
vivek7405 merged commit 94b3b82 into main Jul 22, 2026
10 checks passed
@vivek7405
vivek7405 deleted the feat/auth-gallery-card branch July 22, 2026 10:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant