djangobuilder5 — Milestone 1: redesigned UI vertical slice (React + Vite + Tailwind + shadcn) - #263
Open
mmcardle wants to merge 53 commits into
Open
djangobuilder5 — Milestone 1: redesigned UI vertical slice (React + Vite + Tailwind + shadcn)#263mmcardle wants to merge 53 commits into
mmcardle wants to merge 53 commits into
Conversation
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
…ession Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011jUxCijreThyiaGzxyieYo
… 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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 indjangobuilder.ioordjangobuilder4is touched; this is purely additive.class-variance-authority+clsx+tailwind-merge).#3ECF8Eaccent, 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).models.pypreview with a Copy helper..tar. Editing regenerates the code live..tarcome from@djangobuilder/core, unchanged, isolated behind a singlesrc/domain/adapter. State is local (Zustand + immer +localStorage) — no Firebase in M1.dev5/build_v5/lint_v5/test_v5and foldslint_v5/test_v5into the aggregatelint/test.Design artifacts:
docs/superpowers/specs/2026-07-05-djangobuilder5-ui-redesign-design.mdanddocs/superpowers/plans/2026-07-05-djangobuilder5-milestone-1.md.Deliberate choices / deviations
<select>for M1 (Radix Select can replace later).renderAppFile) rather than the fullasTreeexplorer (deferred).Out of scope (later milestones)
/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_v5→tsc --noEmit+vite buildsucceed.bun run lint && bun run test(aggregate, all packages) pass.bun run dev5→ splash shows livemodels.py+ Copy;/buildthree-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