Skip to content

djangobuilder5 — Milestone 1: redesigned UI vertical slice (React + Vite + Tailwind + shadcn) - #263

Open
mmcardle wants to merge 63 commits into
masterfrom
feat/djangobuilder5-redesign
Open

djangobuilder5 — Milestone 1: redesigned UI vertical slice (React + Vite + Tailwind + shadcn)#263
mmcardle wants to merge 63 commits into
masterfrom
feat/djangobuilder5-redesign

Conversation

@mmcardle

@mmcardle mmcardle commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Summary

Introduces a new front-end package packages/djangobuilder5 — a slick, modern, dark-first redesign of Django Builder — as a look-locking Milestone 1 vertical slice. Nothing in djangobuilder.io or djangobuilder4 is touched; this is purely additive.

  • Stack: React 19 + Vite 6 + TypeScript + Tailwind v4 + shadcn-style owned components (class-variance-authority + clsx + tailwind-merge).
  • Design system: dark-first tokens + light variant with a persisted theme toggle, emerald #3ECF8E accent, and a coding palette exposed as first-class tokens (highlight.js theme is driven by those tokens, so the code colours follow the theme switch).
  • Splash: hero + live generated-models.py preview with a Copy helper.
  • Model builder: three-pane IDE — apps/models tree · inline field & relationship editor · live generated code with file tabs, per-file Copy, and Download .tar. Editing regenerates the code live.
  • Engine reuse: all Django generation + the .tar come from @djangobuilder/core, unchanged, isolated behind a single src/domain/ adapter. State is local (Zustand + immer + localStorage) — no Firebase in M1.
  • Workspace: adds dev5 / build_v5 / lint_v5 / test_v5 and folds lint_v5/test_v5 into the aggregate lint/test.

Design artifacts: docs/superpowers/specs/2026-07-05-djangobuilder5-ui-redesign-design.md and docs/superpowers/plans/2026-07-05-djangobuilder5-milestone-1.md.

Deliberate choices / deviations

  • highlight.js (not Shiki): token-driven theme, synchronous, switches instantly with the theme toggle; matches repo precedent.
  • Native styled <select> for M1 (Radix Select can replace later).
  • Right pane uses fixed file tabs (renderAppFile) rather than the full asTree explorer (deferred).
  • A whole-implementation code review was run and its findings applied (id-based relationship-owner wiring to prevent mis-wiring under duplicate model names; a clipboard guard for non-secure origins).

Out of scope (later milestones)

  • M2: Firebase auth + Firestore persistence, projects dashboard.
  • M3: optional canvas/ERD view mode (state model already shaped for it), production routing/deploy (/db5/ base + hosting), Radix-backed Select/Dialog/Toast.

Test Plan

  • bun install && bun run test_v5 → 30 tests pass (real generator + real store + a live-edit integration test).
  • bun run build_v5tsc --noEmit + vite build succeed.
  • bun run lint && bun run test (aggregate, all packages) pass.
  • bun run dev5 → splash shows live models.py + Copy; /build three-pane editor; edit a field → right-pane code regenerates; Download .tar downloads the project; theme toggle flips dark/light and the code palette follows.

🤖 Generated with Claude Code

https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo

mmcardle and others added 30 commits July 5, 2026 20:21
Design doc for a new React + Vite + Tailwind + shadcn/ui front-end package
(djangobuilder5) replacing the dated Vuetify UI. Milestone 1 is the
look-locking vertical slice: design system (dark-first, emerald accent),
app shell, hero splash with live code preview, and the three-pane IDE model
builder. Uses @djangobuilder/core unchanged; local state, Firebase deferred.

Also gitignore .superpowers/ (visual-companion brainstorm output).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
14-task TDD plan for the look-locking vertical slice: package scaffold,
Tailwind v4 design tokens (dark+light), shadcn foundation, theme toggle,
core domain adapter (@djangobuilder/core), generation + tar, CodeBlock with
token-driven highlighting + copy, Zustand store, app shell, hero splash, and
the three-pane IDE model builder with live regeneration and .tar download.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
Adds djangobuilder5 dev/build/lint/test scripts and folds lint_v5/test_v5
into the aggregate lint/test. Leaves the deploy-oriented build (io+v4)
unchanged; db5 is not deployed in Milestone 1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
…uard

- buildCoreProject: pass 2 now wires relationships onto the core model
  produced in pass 1 by identity (paired list) instead of re-looking up the
  owner by name, so duplicate model names can no longer mis-wire a
  relationship. Removes two non-null assertions. Adds a regression test.
- CodeBlock.copy: guard missing navigator.clipboard and wrap writeText in
  try/catch so copy fails silently on non-secure origins (e.g. LAN IP) instead
  of throwing an unhandled rejection.

Both from the Milestone 1 final code review.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
- Hero column is now top-aligned (items-start) instead of vertically centered
  against the tall code preview, so "Design your models." starts at the top.
- Wider container (max-w-7xl) with a capped text column (~28rem) and a code
  column that grows to fill the remaining space (minmax-based grid), so the
  generated-code panel is wider and responsive — long lines like the
  ForeignKey no longer get clipped.

Addresses layout feedback on the Milestone 1 splash.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
The nav Docs link now uses target="_blank" + rel="noopener noreferrer" and
shows a small external-link icon so it's visually clear it leaves the app.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
Mirrors how djangobuilder4 is served under /db4/:
- db5 build scripts now use --base=/db5/ (+ development/staging/build-only
  variants), and the router uses BrowserRouter basename=import.meta.env.BASE_URL
  so client routing works under the subpath ("/" in dev).
- Root aggregate build/build_development/build_staging/build_production now
  include build_v5(_development/_staging/_production).
- firebase.json rewrites db5/** -> /db5/index.html.
- script/deploy.sh and the Makefile deploy target build db5 and copy its dist
  into the db5/ subdir of the deploy root.

Verified: built index.html emits /db5/assets/..., and the bundle boots and
client-routes correctly when served under /db5/.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
The code pane was a fixed w-[380px] while the editor took all remaining
space. Give it flex-1 (with a 360px floor) so it and the editor split the
space ~50/50 and both scale with the viewport — the generated code is no
longer cramped and the editor no longer hogs the width.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
Design for M2: share the live Firebase backend + 5-collection owner-stamped
schema (via a pure flatten/re-nest mapper), auto-save write-through builder,
full email auth + anonymous, and an A+C projects dashboard (code-thumbnail
cards). Keeps MAX_PROJECTS=3, drops the local-only postgres field.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
11-task TDD plan for auth + Firestore persistence + dashboard: firebase init,
pure renest/summary mapper, auth/data/write services (owner-stamped, cascade),
auth store + firestore-backed write-through project store, builder wiring
(route :id, debounced edits, anon try-it), auth screens, A+C dashboard with
MAX_PROJECTS, and auth-gated routing. Service layer tested with mocked
firebase; dev project is the manual e2e gate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
…on try-it

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
mmcardle and others added 30 commits July 6, 2026 21:31
… auto-select

From the Milestone 2 code review + live e2e findings:
- DebouncedInput: cancel the pending commit on unmount (no updateDoc against a
  deleted doc) and only adopt an external value when not focused (no clobbering
  in-progress keystrokes).
- projectStore: route every write-through op through guardWrite/reportWriteError
  so failed saves log instead of becoming silent unhandled rejections;
  createProject/deleteProject catch too.
- BuilderPage: auto-select the first model once a project's collections load
  (openProject can run before the models snapshot arrives), and add a short
  grace period so a freshly-created project shows Loading rather than flashing
  "Project not found".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
Deploy db5 under /db5/ to the development Firebase project, after fixing the
subpath auth continue-URL + favicon and the four deferred M2 review minors
(snapshot-handler log-not-throw, all-collections-loaded guard, unverified
reload button, atomic batched addModel). Inline execution; staging/prod later.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
- Email action-code continue URL uses import.meta.env.BASE_URL so verified/reset
  users return to /db5/login under the deployed subpath (not the root app).
- Add an inline SVG favicon (kills the 404).
- snapshotErrorHandler logs instead of throwing into onSnapshot's async machinery.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
subscribeAll now reports allLoaded (true once every collection's initial
snapshot has arrived); the store sets dataLoaded from it. Fixes the
cascade-delete race window, the brief "Project not found" flash, and makes
first-model auto-select reliable.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
Add reloadUser() and an "I've verified — refresh" button that reloads the user
from the server, pushes it into the auth store, and navigates to /projects when
verified — no manual page reload needed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
addModel now writes the model doc, the app-map link, and the two default
DateTimeField fields (created/last_updated) in a single writeBatch — atomic
and one round-trip instead of four sequential writes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RakQgqBxYPYUY37gvxrtG7
…t, responsive

Closes the five parity gaps vs the current system:
- Project files: CodePane now renders the full project file tree
  (renderer.asTree) — project/app/model files, click to view — not just the
  five app files. Adds projectFileTree + renderNodeByPath to domain/generate;
  exports DjangoProjectFileResource from core.
- Description + settings: new ProjectHeader (name, description, version/HTMX/
  Channels chips) + ProjectSettingsDialog (edit name/description/version/flags
  write-through, delete project). Adds store setDescription.
- About: new /about route + AboutView + TopNav link.
- Responsive: new BuilderShell — 3-pane on lg+, tree drawer + Edit/Code tab
  switcher below lg.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RakQgqBxYPYUY37gvxrtG7
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RakQgqBxYPYUY37gvxrtG7
Replace the four-column builder (models tree | editor | file tree | code)
with a two-column tabbed workspace: a persistent models tree plus a main
area that tabs between Design (model editor) and Code (file tree + code).
Only one content pane shows at a time, at every width, so nothing is cramped.
Makes the existing mobile tab pattern the layout at all breakpoints.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RakQgqBxYPYUY37gvxrtG7
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RakQgqBxYPYUY37gvxrtG7
Collapse the builder to a single navigation tree (the generated file tree)
plus the code view; move all model editing into a per-app modal.

- Remove the models panel (TreePane) and the Design/Code tabs (EditorPane,
  CodePane deleted). BuilderShell is now: file tree (persistent lg / drawer
  below lg) + CodeView, with a per-app ModelsModal.
- ModelsModal lists every model in an app (ModelEditor each: name, abstract,
  fields, relationships, delete), plus Add model and Delete app. Opened from
  the tree's edit control on models.py or the code header's 'Edit models'.
- FileTree gains a '+ App' input and a per-models.py edit control.
- Add app-level creation to the tree; add store updateModel + removeApp
  (writes.removeApp cascade); drop the now-unused select/selectedModelId.
- Promote DebouncedInput to a shared ui component.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RakQgqBxYPYUY37gvxrtG7
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RakQgqBxYPYUY37gvxrtG7
- core: add DJANGO6 = 6.0 to the DjangoVersion enum (additive; db4 unaffected).
- db5: DjangoVersionNumber 3|4|5|6; toVersionNumber(6)->6.0; fromVersion default 6;
  buildCoreProject maps 6 -> DJANGO6; LocalProject/ProjectSummary version types.
- dialogs: add 'Django 6' option, preselected by default, in New-project + Settings.

Note: the numeric enum renders the pin as 'Django==6' (pip resolves to 6.0).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RakQgqBxYPYUY37gvxrtG7
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RakQgqBxYPYUY37gvxrtG7
…de, built-in targets, consent/analytics

Closes the High + Medium gaps vs djangobuilder.io:
- Import from models.py: core ModelImporter wrapped in domain/import.ts;
  writes.importModels batches parsed models+fields+rels; ImportModelsDialog
  (paste -> parse -> select -> add) opened from the models modal.
- Model inheritance/parents: LocalModel.parents in the shared Firestore format
  ({class,type:django} | {app,model,type:user}); mapper reads + filters dangling;
  buildCoreProject resolves django + user parents; ModelEditor 'Inherits from' UI.
- Move model between apps: writes.moveModel re-parents via the app maps; a
  'Move to…' select in the model editor.
- Anonymous -> registered upgrade: auth.upgradeAnonymous (linkWithCredential),
  UpgradeAccountDialog, 'Save your account' in the nav — same uid, data kept.
- Extra built-in targets: auth.AbstractUser/AbstractBaseUser/Group as relationship
  targets; buildCoreProject resolves any built-in; shared builtInTargets.
- Analytics + consent + privacy: consentStore, gated gtag loader, ConsentSnackbar,
  /privacy PrivacyPolicy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RakQgqBxYPYUY37gvxrtG7
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RakQgqBxYPYUY37gvxrtG7
At >=1536px the per-app models editor renders as a right-rail side panel
next to the live code (edit + watch models.py regenerate together) instead
of a centered overlay; below that width it stays the modal.

- extract ModelsPanel (the editor content) from ModelsModal; ModelsModal is
  now a thin overlay wrapper around it.
- add a matchMedia-based useMediaQuery hook (+ jsdom mock in test setup).
- BuilderShell docks ModelsPanel (right rail) when the 2xl query matches,
  else renders the ModelsModal overlay.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RakQgqBxYPYUY37gvxrtG7
The relationship row had a fixed-width name input plus two intrinsic-width
selects (type + target) and no flex-1 absorber, so its min content width
(~548px) exceeded the narrow docked panel (~469px) and spilled past the edge.
Make both selects min-w-0 flex-1 so they share the row and shrink (like the
field row's args input). Verified live: row now fits its container exactly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RakQgqBxYPYUY37gvxrtG7
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RakQgqBxYPYUY37gvxrtG7
On >=1536px the docked models editor is now a permanent right rail — no
close/Done — that edits the app of the file you're viewing (follows tree
navigation, keeps the last app on project-level files, re-points if its app
is deleted). 'Edit models'/tree ✎ on large screens navigate to that app's
models.py instead of opening anything. Below the breakpoint it stays the
closable modal.

- ModelsPanel onClose is now optional (absent = non-closable: hides ✕/Done).
- BuilderShell derives a dockedAppId and always renders the panel when wide.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RakQgqBxYPYUY37gvxrtG7
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RakQgqBxYPYUY37gvxrtG7
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RakQgqBxYPYUY37gvxrtG7
Field/relationship arguments were crammed into a shrinking inline input (and
relationship args weren't editable at all). Give args their own full-width line
below the controls, as a wrapping, auto-growing textarea (DebouncedTextarea):
long values wrap into view instead of clipping, and relationship args
(on_delete, related_name, …) are now editable. Enter is suppressed / newlines
stripped so args stay a single logical line.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RakQgqBxYPYUY37gvxrtG7
Shorter controls (h-8), a smaller args textarea, and tighter section/row
spacing bring each field block from ~78px to ~66px. Args still wrap when long.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RakQgqBxYPYUY37gvxrtG7
On large screens the models panel is always docked, so the tree's ✎ control
and the code header's '✎ Edit models' button are redundant. Gate both on the
docking breakpoint (BuilderShell passes onEditModels to FileTree/CodeView only
below it); selecting a models.py row still switches the docked panel. Below the
breakpoint both remain and open the modal.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RakQgqBxYPYUY37gvxrtG7
Pre-deploy pass over djangobuilder5, driven by a feature diff against the
production .io app.

Data integrity:
- Chunk every unbounded batch at 450 writes. importModels, removeModel,
  removeApp and deleteProjectCascade each built a single WriteBatch, so a
  ~40-model import or a large project delete blew Firestore's 500-op cap and
  failed outright. Write order is now deliberate — children before the link
  that reveals them, descendants before the parent — so a failed chunk leaves
  recoverable state.
- Cascade relationship targets. `to` is a denormalised "app.Model" string, so
  renaming an app or model, moving a model, or deleting either one stranded
  every relationship pointing at it. domain/relationshipIntegrity.ts computes
  the repoints (rename/move) and the inbound deletes, applied in the same run.
- Tolerate an unresolved target in buildCoreProject instead of throwing. The
  five collection listeners deliver snapshots independently, so a renamed app
  can land a frame before its repointed relationship — and BuilderShell renders
  the file tree unguarded, which took the whole page down. Found only by
  exercising a rename against live Firestore.

Parity gaps:
- Apps can now be renamed (previously delete-and-recreate, losing every model).
- Anonymous sign-in from /login, not just the splash CTAs.
- Signing out as a guest warns before stranding the data, and offers deleting
  it; previously it signed out silently and orphaned the docs forever.
- Name validation on everything that becomes a Python identifier — rejects
  spaces, leading digits, punctuation and keywords rather than generating
  unimportable code.
- MAX_MODELS_PER_APP (25), matching .io.
- Failed snapshot listeners surface a banner; they never recover, so the page
  was silently showing stale data.
- Import accepts .py uploads and routes each parsed model to a chosen app.

Also: the wordmark links home rather than to /projects, and the splash drops
"Live demo", which fired the identical handler as the primary CTA and landed
users on an empty dashboard.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A new account landed on "Your projects / 0 of 3", an empty grid and a modal
behind a button — nothing about what the product does.

With no projects, /projects now renders inline (no dialog): a short hero, the
create form, and the real generated models.py / admin.py / serializers.py /
views.py / urls.py for a starter blog app, tabbed and highlighted. The project
name flows live into the preview as it is typed, and a three-step strip spells
out the workflow.

The hints are derived, not hardcoded: countProjectFiles and generatedFileNames
walk the actual rendered tree, and the output chips are a curated list filtered
against what the renderer really emits — so the page can't promise a file that
is no longer produced. Toggling HTMX or Channels does not change the file tree
(only contents and requirements), so the copy doesn't claim it does.

Extracts ProjectForm, shared with NewProjectDialog, so the inline and modal
paths can't drift on validation or create-then-navigate.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CI had jobs for core, .io and the CLI but none for db5, so its suite (now 192
tests) only ran locally. Adds v5_tests and v5_type_check alongside io_tests,
plus the db5 dist artifact.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant