Damm's delivery-route planner. Turns a fleet, a list of clients, and their delivery windows into optimized truck routes — driver, vehicle, stop order, pallet layout, and the full timeline for the day. Compares the optimizer's plan against the baseline so dispatchers can see what changes and why before sending a truck out.
Built for the Damm × Interhack BCN hackathon.
- Next.js 15 App Router (Turbopack dev) on React 19
- TypeScript, Tailwind CSS v4, base-ui + shadcn primitives
- MapLibre GL for the planner map (zone clusters, arc layers, route lines)
- react-hook-form + zod at every form boundary
- TanStack Table for the data grids
- motion for the polish (shiny CTA, shimmer loaders, modal resize)
- three.js + @react-three/fiber for the truck pallet visualization
This frontend talks to the damm-backend FastAPI server. Start the backend first (default http://localhost:8000).
pnpm install
pnpm dev # http://localhost:3000 — Turbopack
pnpm typecheck
pnpm buildOverride the backend URL with an env var if it lives elsewhere:
NEXT_PUBLIC_API_BASE_URL=http://10.0.0.5:8000 pnpm devDefault is http://localhost:8000. See src/lib/api/client.ts.
The planner assistant (see Planner agent below) needs a Google Generative AI key in .env:
GOOGLE_GENERATIVE_AI_API_KEY=<your key>All reads and writes go through a thin Zod-validated client in src/lib/api/:
| Module | Hits | Used for |
|---|---|---|
catalog.ts |
/api/v1/db/{customers,trucks,drivers} |
Catalog tables (/clients, /trucks, /drivers) |
warehouses.ts |
/api/v1/db/warehouses (+ catalog POST/PATCH/DELETE) |
Centers list + Add/Edit/Delete center modals |
transports.ts |
/api/v1/data/transports and /transport/{id} |
Routes table on a center, route detail in RouteHero |
orders.ts |
/api/v1/db/orders |
Derives the available-dates set for the date picker |
optimize.ts |
/api/v1/optimize/full/preview and /persist |
Generates and saves suggested routes from AddRouteModal |
The optimizer runs in preview mode when the user clicks Generate Routes — three parallel calls with different parameters give three suggestions in ~20s. Save selected route then calls /optimize/persist to commit it as a real transport.
A read-only chat assistant lives in the right-hand panel on every app surface. It's powered by Gemini 2.5 Flash via @ai-sdk/google, with streaming through Vercel's AI SDK.
What makes it useful is the surface awareness: every page publishes its visible state (which center, which route, which catalog, which selected row) into a chat context, and src/agents/visible-context.ts turns that into a deterministic JSON snapshot that's injected into the system prompt for each request. The model only answers from what's actually on screen — no invented stops, no hallucinated drivers — and points users at the right UI control when they ask for an action it can't take.
| Piece | Path |
|---|---|
| System prompt + model config | src/agents/planner.ts |
| Surface → JSON snapshot builder | src/agents/visible-context.ts |
| Streaming endpoint | src/app/api/chat/route.ts |
| UI shell (panel, bubbles, input) | src/components/chat/ |
src/
app/ Next App Router — (app) and (auth) groups
components/
auth/ Login screen
centers/ Warehouse list + detail; Add/Edit modals
clients/ Customer table (lives off backend)
drivers/ trucks/ Catalog tables (live off backend)
routes/ Route table, hero, map view, AddRouteModal,
RouteReviewPanel (zone clusters), 3D truck viz
shared/ DataTable, ConfirmDeleteDialog, generic patterns
shell/ App chrome (header, sidebar, layout)
ui/ base-ui wrappers, MapLibre primitives,
ShinyText / TextShimmer / WanderingEyes
lib/
api/ Backend client (see Backend wiring table above)
chat/ Planner chat surface + visible-context builder