Files
Codewalkers/.planning/phases/16-frontend-scaffold/16-04-PLAN.md
Lukas May 0ff65b0b02 feat: Rename application from "Codewalk District" to "Codewalkers"
Update all user-facing strings (HTML title, manifest, header logo,
browser title updater), code comments, and documentation references.
Folder name retained as-is.
2026-03-05 12:05:08 +01:00

10 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous
phase plan type wave depends_on files_modified autonomous
16-frontend-scaffold 04 execute 3
16-03
packages/web/package.json
packages/web/src/App.tsx
packages/web/src/routeTree.gen.ts
packages/web/src/router.tsx
packages/web/src/routes/__root.tsx
packages/web/src/routes/index.tsx
packages/web/src/routes/initiatives/index.tsx
packages/web/src/routes/initiatives/$id.tsx
packages/web/src/routes/inbox.tsx
packages/web/src/layouts/AppLayout.tsx
packages/web/src/components/ui/button.tsx
packages/web/src/components/ui/badge.tsx
packages/web/src/components/ui/card.tsx
packages/web/src/components/ui/dropdown-menu.tsx
true
Set up TanStack Router with page stubs and the app shell layout (navigation bar) matching the wireframe header.

Purpose: Establish the navigation structure and persistent layout that all subsequent screens plug into. Phase 17-19 will implement the actual page content; this plan creates the skeleton they slot into. TanStack Router provides fully type-safe routing with validated params and search params. Output: Working router with 3 page stubs (Dashboard, Initiative Detail, Inbox) and persistent nav header.

<execution_context> @/.claude/get-shit-done/workflows/execute-plan.md @/.claude/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md

Wireframe navigation structure

@docs/wireframes/initiative-dashboard.md

tRPC client from Plan 03

@packages/web/src/lib/trpc.ts @packages/web/src/main.tsx

Task 1: Install TanStack Router and add shadcn/ui base components packages/web/package.json, packages/web/src/components/ui/button.tsx, packages/web/src/components/ui/badge.tsx, packages/web/src/components/ui/card.tsx, packages/web/src/components/ui/dropdown-menu.tsx 1. Install in packages/web: - Dependencies: `@tanstack/react-router` - Dev dependencies: `@tanstack/router-plugin` (Vite plugin for route generation), `@radix-ui/react-dropdown-menu`, `@radix-ui/react-slot` (shadcn/ui primitives)
  1. Update packages/web/vite.config.ts to add the TanStack Router Vite plugin:

    import { TanStackRouterVite } from '@tanstack/router-plugin/vite'
    
    export default defineConfig({
      plugins: [
        TanStackRouterVite(),
        react(),
      ],
      // ... existing proxy config
    })
    

    The TanStack Router plugin must come BEFORE the react plugin. It auto-generates the route tree from the file-based routes in src/routes/.

  2. Add the 4 most-needed shadcn/ui components. Use npx shadcn@latest add button badge card dropdown-menu from packages/web directory. If the CLI doesn't work with this directory structure, manually create the component files following the shadcn/ui source (available at ui.shadcn.com).

    The components go in packages/web/src/components/ui/:

    • button.tsx — needed by every page (View, Spawn, Queue, etc.)
    • badge.tsx — needed for StatusBadge component
    • card.tsx — needed for InitiativeCard
    • dropdown-menu.tsx — needed for ActionMenu and SpawnArchitectDropdown

    These are the foundation components. Additional shadcn components will be added in later phases as needed.

  3. Run npm install from root. cd packages/web && npx vite build succeeds. Component files exist in packages/web/src/components/ui/. TanStack Router and shadcn/ui base components installed.

Task 2: Create file-based routes, app shell layout, and page stubs packages/web/src/App.tsx, packages/web/src/router.tsx, packages/web/src/routes/__root.tsx, packages/web/src/routes/index.tsx, packages/web/src/routes/initiatives/index.tsx, packages/web/src/routes/initiatives/$id.tsx, packages/web/src/routes/inbox.tsx, packages/web/src/layouts/AppLayout.tsx 1. Create file-based route structure in `packages/web/src/routes/`:

TanStack Router uses file-based routing. The Vite plugin generates routeTree.gen.ts automatically from the file structure:

  • __root.tsx — Root layout route (wraps all pages with AppLayout)
  • index.tsx/ route, redirects to /initiatives
  • initiatives/index.tsx/initiatives DashboardPage
  • initiatives/$id.tsx/initiatives/$id InitiativeDetailPage (type-safe param)
  • inbox.tsx/inbox InboxPage
  1. Create packages/web/src/routes/__root.tsx: The root route wraps all pages with the AppLayout shell:

    import { createRootRoute, Outlet } from '@tanstack/react-router'
    import { AppLayout } from '../layouts/AppLayout'
    
    export const Route = createRootRoute({
      component: () => (
        <AppLayout>
          <Outlet />
        </AppLayout>
      ),
      notFoundComponent: () => (
        <div className="p-8 text-center">
          <h1 className="text-2xl font-bold">Page not found</h1>
          <p className="text-muted-foreground mt-2">The page you're looking for doesn't exist.</p>
        </div>
      ),
    })
    
  2. Create packages/web/src/routes/index.tsx: Redirect root / to /initiatives:

    import { createFileRoute, redirect } from '@tanstack/react-router'
    
    export const Route = createFileRoute('/')({
      beforeLoad: () => {
        throw redirect({ to: '/initiatives' })
      },
    })
    
  3. Create packages/web/src/routes/initiatives/index.tsx: Dashboard stub:

    import { createFileRoute } from '@tanstack/react-router'
    import { trpc } from '../../lib/trpc'
    
    export const Route = createFileRoute('/initiatives/')({
      component: DashboardPage,
    })
    
    function DashboardPage() {
      const health = trpc.health.useQuery()
      return (
        <div>
          <h1 className="text-2xl font-bold">Initiative Dashboard</h1>
          <p className="text-muted-foreground mt-2">
            Server: {health.data?.status ?? 'connecting...'}
          </p>
          <p className="text-muted-foreground mt-1">Content coming in Phase 17</p>
        </div>
      )
    }
    
  4. Create packages/web/src/routes/initiatives/$id.tsx: Detail stub with type-safe params:

    import { createFileRoute } from '@tanstack/react-router'
    
    export const Route = createFileRoute('/initiatives/$id')({
      component: InitiativeDetailPage,
    })
    
    function InitiativeDetailPage() {
      const { id } = Route.useParams()
      return (
        <div>
          <h1 className="text-2xl font-bold">Initiative Detail</h1>
          <p className="text-muted-foreground mt-2">Initiative ID: {id}</p>
          <p className="text-muted-foreground mt-1">Content coming in Phase 18</p>
        </div>
      )
    }
    
  5. Create packages/web/src/routes/inbox.tsx: Inbox stub:

    import { createFileRoute } from '@tanstack/react-router'
    
    export const Route = createFileRoute('/inbox')({
      component: InboxPage,
    })
    
    function InboxPage() {
      return (
        <div>
          <h1 className="text-2xl font-bold">Agent Inbox</h1>
          <p className="text-muted-foreground mt-1">Content coming in Phase 19</p>
        </div>
      )
    }
    
  6. Create packages/web/src/layouts/AppLayout.tsx: The persistent navigation shell from the wireframe header:

    CODEWALK DISTRICT                                    [+ New Initiative]
    Initiatives    Agents    Tasks    Settings
    

    Implementation:

    • Header with app title "Codewalkers" on the left
    • "New Initiative" button on the right (placeholder handler for now)
    • Navigation tabs: Initiatives (links to /initiatives), Inbox (links to /inbox)
    • Skip "Agents", "Tasks", "Settings" tabs for now — not in Phase 16-19 scope. Include them as disabled/greyed out.
    • Use Link from @tanstack/react-router for navigation links
    • Active nav item highlighted using activeProps or activeOptions on Link
    • Children rendered via props.children (passed from root route Outlet)
    • Minimal Tailwind styling: fixed header, content below with padding
  7. Create packages/web/src/router.tsx:

    import { createRouter } from '@tanstack/react-router'
    import { routeTree } from './routeTree.gen'
    
    export const router = createRouter({ routeTree })
    
    declare module '@tanstack/react-router' {
      interface Register {
        router: typeof router
      }
    }
    
  8. Update packages/web/src/App.tsx: Replace the temporary health-check component with the router:

    import { RouterProvider } from '@tanstack/react-router'
    import { router } from './router'
    
    function App() {
      return <RouterProvider router={router} />
    }
    
    export default App
    
  9. Run cd packages/web && npx vite build — the TanStack Router plugin will generate routeTree.gen.ts during the build. The generated file should be committed to git (it's a type-safe route manifest).

Keep it simple. These are stubs — the real UI comes in Phases 17-19. The goal is a working navigation skeleton with the right route structure. cd packages/web && npx vite build succeeds. routeTree.gen.ts generated with routes: /, /initiatives, /initiatives/$id, /inbox. AppLayout renders header and child content. TanStack Router configured with file-based routes. App shell layout renders nav header. Page stubs in place for Phases 17-19 to fill in.

Before declaring plan complete: - [ ] `cd packages/web && npx vite build` succeeds - [ ] Route `/initiatives` renders DashboardPage stub - [ ] Route `/initiatives/some-id` renders InitiativeDetailPage stub with type-safe param - [ ] Route `/inbox` renders InboxPage stub - [ ] AppLayout nav header present on all pages - [ ] Active nav item highlighted - [ ] routeTree.gen.ts generated

<success_criteria>

  • TanStack Router configured with file-based routes
  • Type-safe params on /initiatives/$id route
  • AppLayout shell matches wireframe header structure
  • Page stubs ready for Phase 17-19 implementation
  • Navigation between pages works
  • Build passes cleanly </success_criteria>
After completion, create `.planning/phases/16-frontend-scaffold/16-04-SUMMARY.md`