DEV Community

agile turtles
agile turtles

Posted on

We built an admin dashboard that Claude can reshape into anything — here's how

We just put out Dashwise over at agile turtles. It's an admin dashboard kit where every directory has a CLAUDE.md — so you can open it in Claude Code, say "make this into a CRM" or "turn this into a project tracker", and it actually works. The AI knows the architecture, the conventions, and where everything goes.

Before we get into the AI stuff — the stack. We went with the latest everything.

Here's the demo if you want to click around first.


the stack

  • Next.js 16.1 with Turbopack as the default bundler. View Transitions baked in. No config needed — one flag in next.config.ts and every <Link> navigation gets a smooth crossfade.
  • React 19.2startTransition driving those View Transitions, plus all the Server Component stuff actually working properly now.
  • Tailwind CSS v4 — this is a big one. The whole color system moved from hsl to oklch. Perceptually uniform colors. You can build a theme switcher by rotating one hue value and every color in the palette stays visually consistent. Try doing that with hsl.
  • shadcn/ui on the latest — 31 components, all pre-installed. We didn't touch any of them. That's the rule: npx shadcn@latest add, never hand-edit.
  • zod 4 — breaking changes from v3, nothing dramatic but enough to burn an afternoon if you're not paying attention. required_error is now just error. .refine() breaks TypeScript inference with zodResolver and you need a gnarly type assertion.
  • @dnd-kit for drag-and-drop — not react-beautiful-dnd (deprecated), not react-dnd (painful API). @dnd-kit with the DragOverlay pattern for proper cross-column kanban dragging.
  • TanStack Table 8 — headless, typed, does sorting/filtering/pagination without fighting you.
  • Recharts 3.7 — clean API, works well with Server Components.

Everything runs on Node 20.9+. npm install && npm run dev and you're up. No Docker, no database, no env vars to configure.


oklch changed how we think about theming

This deserves its own section because it changes how theming works.

Tailwind v4 defaults to oklch. The "L" channel is perceptually uniform — a blue at oklch(0.6 0.15 265) and a green at oklch(0.6 0.15 150) actually look the same brightness. With hsl, that was never true. Colors at "50% lightness" looked wildly different depending on the hue.

We built a 6-color theme switcher on top of this. Each preset just rotates the hue:

:root { --primary: oklch(0.488 0.243 264.376); }           /* violet */
[data-color="blue"] { --primary: oklch(0.488 0.243 240); }  /* blue */
[data-color="green"] { --primary: oklch(0.488 0.243 150); } /* green */
Enter fullscreen mode Exit fullscreen mode

All six look coherent without manual per-color tuning. That's oklch doing the work.

The catch: if you write hsl(var(--primary)) out of muscle memory (or because you copied from an old shadcn/ui tutorial), nothing renders. No error. Just invisible elements. We stared at a blank screen for an hour before figuring that one out. Everything in the project uses Tailwind semantic classes — bg-primary, text-muted-foreground — and we documented this in the CLAUDE.md files so nobody else (human or AI) repeats it.


the AI-native thing — why it matters

Every directory has a CLAUDE.md:

CLAUDE.md              — project overview, architecture, common tasks
src/app/CLAUDE.md      — routing patterns, how to add pages
src/components/CLAUDE.md — component conventions, what not to touch
src/lib/CLAUDE.md      — data layer, schemas, utilities
src/hooks/CLAUDE.md    — hook patterns
src/types/CLAUDE.md    — type conventions
Enter fullscreen mode Exit fullscreen mode

These aren't regular docs. They're structured context for AI coding assistants. Each one covers how to add new things (with copy-paste templates), conventions that aren't obvious from the code, and gotchas that would waste time.

Real example. You open the project in Claude Code and say:

"Add an invoices page with a table showing invoice number, client, amount, status, and due date."

Without CLAUDE.md, the AI would probably put things in weird places, use hsl() for colors, add event handlers to Server Components, and build a table from scratch instead of using TanStack Table.

With the CLAUDE.md chain, it:

  1. Creates the page in src/app/(dashboard)/invoices/page.tsx as a Server Component
  2. Puts the interactive bits in a separate "use client" file
  3. Defines columns following the existing TanStack Table pattern
  4. Adds mock data with // TODO: Replace with your API call markers
  5. Adds the sidebar nav item
  6. Creates a loading skeleton

Same patterns, same structure, same conventions as the rest of the codebase.


what you can build with it

Dashwise ships as a generic admin dashboard — 10 pages, 5 auth flows, theme customizer. But because of the CLAUDE.md files, you can reshape it into pretty much anything:

  • SaaS dashboard — swap mock data for your API, add billing, ship it
  • project management tool — kanban board is already built, add projects and teams
  • CRM — tables, profile page, inbox are your starting point
  • analytics platform — charts page + theme customizer = white-label analytics
  • client portal — auth pages exist, add role-based views
  • internal tool — forms and settings are ready, hook up your internal APIs

The CLAUDE.md files guide the AI to follow existing patterns. You describe what you want, and it builds it consistently with the rest of the codebase.


the architecture (kept simple on purpose)

We kept things predictable because that's what makes AI assistance actually useful.

Every page follows one pattern:

export const metadata: Metadata = { title: "Kanban" }

export default function KanbanPage() {
  return (
    <div className="space-y-6">
      <PageHeader title="Kanban Board" description="Drag and drop tasks" />
      <KanbanContent />  {/* "use client" — all state lives here */}
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

Server Component exports metadata. Client Component handles interaction. Every single page. No exceptions.

All data comes from one file:

import { kanbanTasks } from "@/lib/mock-data" // TODO: Replace with your API call
Enter fullscreen mode Exit fullscreen mode

grep -r "TODO: Replace" finds every integration point. When you connect a real backend, you know exactly what to swap.

Route groups split the layouts:

(dashboard)/ wraps pages in sidebar + topbar. (auth)/ wraps pages in a full-screen gradient layout. The parentheses don't show up in URLs. Clean separation, no layout nesting headaches.


stuff that bit us

We documented these in the CLAUDE.md files so neither you nor the AI repeat them:

  • oklch not hsl — invisible elements, no error, nothing. use Tailwind classes only.
  • Server Component event handlers — we added an onClick to a page file. twice. React just silently ignores it. the interactive stuff has to live in a "use client" file.
  • zod 4 migrationerror instead of required_error. small change, silent breakage. .refine() needs a type assertion with zodResolver or TypeScript complains.
  • @dnd-kit click vs drag — without activationConstraint: { distance: 5 }, every tiny mouse movement during a click triggers a drag. buttons on kanban cards become unusable.
  • shadcn/ui files — never edit components/ui/ directly. we learned this the hard way when an update overwrote our changes.

links

agile turtles on gumroad. MIT license. BFF — no subscriptions, no lock-in.

demo: dashwise.netlify.app

if you end up building something with it, we'd like to hear about it.

Top comments (0)