|
| 1 | +# 0047 — App shell — READY FOR UI REVIEW |
| 2 | + |
| 3 | +## What landed |
| 4 | + |
| 5 | +- shadcn primitives added under the existing `base-nova` Base UI |
| 6 | + preset: `sidebar`, `dropdown-menu`, `avatar`, `skeleton`, |
| 7 | + `tooltip`, `separator`, `empty` (and `sheet`, `input` as deps). |
| 8 | +- `web/src/routes/_app.tsx` — protected layout. `beforeLoad` calls |
| 9 | + `queryClient.ensureQueryData({ queryKey: ["me"], queryFn: |
| 10 | + apiGet("/me") })`; an `ApiError(401)` throws `redirect({ to: |
| 11 | + "/login" })`. The guard runs before render so there's no |
| 12 | + flicker. |
| 13 | +- `app-shell/sidebar.tsx` — collapsible-icon Sidebar with two |
| 14 | + groups: |
| 15 | + - Insights: Dashboard, Repos, Orgs, Engineers |
| 16 | + - Workspace: Connections, Sync, Settings |
| 17 | + Active state via TanStack Router's pathname + the Sidebar |
| 18 | + component's `isActive`. Footer shows version from |
| 19 | + `/api/v1/system/health`. |
| 20 | +- `app-shell/topbar.tsx` — SidebarTrigger + section title + theme |
| 21 | + menu (light / dark / system) + user dropdown (email/role label, |
| 22 | + logout button). |
| 23 | +- `app-shell/placeholder.tsx` — shared shadcn `Empty` wrapper used |
| 24 | + by every placeholder route, with a task-id chip pointing at the |
| 25 | + task that will fill it in. |
| 26 | +- Stub `/login` and `/register` routes (0048 wires the forms). |
| 27 | +- Root `/` redirects to `/dashboard`. |
| 28 | +- ESLint: `react-refresh/only-export-components` is scoped off for |
| 29 | + `src/components/ui/**` (shadcn-generated) and `src/routes/**` |
| 30 | + (TanStack file routes export `Route` + component by design). |
| 31 | + |
| 32 | +## Verify output |
| 33 | + |
| 34 | +``` |
| 35 | +== pnpm typecheck == |
| 36 | +> tsc --noEmit |
| 37 | +== pnpm lint == |
| 38 | +> eslint . |
| 39 | +== pnpm build == |
| 40 | +> tsc -b && vite build |
| 41 | +✓ built in 1.72s |
| 42 | +``` |
| 43 | + |
| 44 | +## How to view it locally |
| 45 | + |
| 46 | +From the repo root: |
| 47 | + |
| 48 | +```bash |
| 49 | +make dev |
| 50 | +# Go API → http://localhost:8080 |
| 51 | +# Vite SPA → http://localhost:5173 (proxies /api → :8080) |
| 52 | +``` |
| 53 | + |
| 54 | +Then in your browser: |
| 55 | + |
| 56 | +- **`http://localhost:5173/`** — should redirect to `/dashboard`, |
| 57 | + which 401s (no session) and lands you on `/login` (stub). |
| 58 | +- **`http://localhost:5173/register`** — stub form placeholder |
| 59 | + (0048 fills it in). |
| 60 | +- **Manually create an account** via `curl` so you can poke the |
| 61 | + shell with a real session: |
| 62 | + |
| 63 | + ```bash |
| 64 | + curl -X POST http://localhost:5173/api/v1/auth/register \ |
| 65 | + -H "Content-Type: application/json" \ |
| 66 | + -c /tmp/tempo.cookies \ |
| 67 | + -d '{"email":"admin@example.com","password":"hunter22hunter22"}' |
| 68 | + ``` |
| 69 | + |
| 70 | + Then drop `/tmp/tempo.cookies` into the browser via the devtools |
| 71 | + Application → Cookies panel (cookie name: `tempo_session`), or |
| 72 | + hit `/api/v1/auth/login` from a tab that already has the cookie. |
| 73 | + |
| 74 | +- **With a session**, visit `/dashboard` — you should see the |
| 75 | + sidebar (collapsible via `cmd-B` or the trigger), the topbar |
| 76 | + with theme menu + user dropdown, and the placeholder card. |
| 77 | + Click through Repos / Orgs / Engineers / Connections / Sync / |
| 78 | + Settings — each shows its own placeholder with a "coming in |
| 79 | + 00XX" chip. |
| 80 | + |
| 81 | +## What to design-review |
| 82 | + |
| 83 | +Conservative defaults — I kept the visual language close to the |
| 84 | +`base-nova` preset that's already locked in. Things to evaluate: |
| 85 | + |
| 86 | +- **Sidebar branding.** Header has a square `t` mark + "tempo" |
| 87 | + wordmark + "engineering insights" eyebrow. Footer shows the |
| 88 | + build version. Adjust mark / wordmark style if it doesn't read |
| 89 | + right. |
| 90 | +- **Nav grouping.** Insights vs Workspace split — does that feel |
| 91 | + natural, or should everything be one group? |
| 92 | +- **Icons** (lucide): Gauge / BarChart3 / Building2 / Users / |
| 93 | + Plug / RefreshCw / Settings. Swap any that don't fit your |
| 94 | + mental model. |
| 95 | +- **Topbar density.** h-14 with sidebar-trigger + title + theme + |
| 96 | + avatar. Comfortable, or too sparse / too dense? |
| 97 | +- **Theme toggle.** Three options (light/dark/system); inline |
| 98 | + with the menu rather than a one-click toggle. The existing |
| 99 | + `d` keyboard shortcut still works. |
| 100 | +- **User menu.** Just Account (disabled, "coming soon") + Log |
| 101 | + out. Anything you want surfaced here? |
| 102 | +- **Placeholder treatment.** Card-like `Empty` centered in the |
| 103 | + main area. Want them more compact / more prominent? |
| 104 | +- **Spacing and motion.** Default shadcn animations on dropdowns; |
| 105 | + no custom motion yet. |
| 106 | + |
| 107 | +## Notes / known limitations |
| 108 | + |
| 109 | +- `/login` and `/register` are placeholder cards. 0048 wires the |
| 110 | + actual forms; the redirect chain already routes there. |
| 111 | +- The version pulled from `/system/health` is the Go-side |
| 112 | + `version.Version` (currently `dev` or commit SHA, `docker` in |
| 113 | + the container image). |
| 114 | +- "Account (coming soon)" item in the user menu is a hook for a |
| 115 | + future profile page; remove it if we never plan one. |
| 116 | +- Mobile: the sidebar collapses into a Sheet on small viewports |
| 117 | + (`use-mobile.ts` from shadcn handles the breakpoint). Worth a |
| 118 | + quick check at viewport widths < 768px. |
| 119 | + |
| 120 | +When you're happy, run `/finish-task 0047` and I'll move on to |
| 121 | +0048 (auth pages). |
0 commit comments