Projects
AI-assisted trip planning, and the agency console on top of it

TripBox

Two-sided travel platform: travellers plan multi-destination trips with AI-generated itineraries and multi-currency settlement, agencies run branded client operations on the same engine.

Role
Solo — architecture, backend, interface, design system
Period
2025 — Present
Type
Platforms
Status
production
515k
Lines of TypeScript
418
API routes
50
Feature modules
500
Test files
01

Showcase

3 videos
Loading showcase
33sTripBox — The trip hub, the day board and an AI-drafted day that has to survive validation. Rendered live with Remotion, not a video file.
02

Overview

Serious trip planning is a spreadsheet-and-tabs problem: fragmented, error-prone around money and dates, painful to share. TripBox makes the hard parts — currencies, splits, multi-leg transport, group permissions — precise, and puts an AI planner on top that has to respect real opening hours and real travel times.

It is two products sharing one engine. Travellers get the trip builder, the day boards and the settlement maths. Travel agencies get a console on the same data: branded client-facing storefronts, lead and commission management, payment plans and DMC settlement. The B2B surface is the consumer app with more power, not a bolted-on enterprise panel.

The codebase is 50 feature modules with hard boundaries over a Supabase Postgres database, 418 API routes, and roughly 515,000 lines of TypeScript.

03

Architecture

4 diagrams
01

System architecture

mcpTraveller PWAAgency consoleAI assistant418 routesauth, idempotency50 featuremodulesPostgresrow-level securityClaudeMapbox GLThree.js globe

Scroll to pan

Three front doors onto one engine. The MCP surface is a client like any other — an assistant reaches the same routes a browser does, under the same permissions.
02

Itinerary generation

ChangeCheckGeneratecoherentmuseum at 3amDates, places,preferencesConstraint sethours, travel timeClaudeday by dayValidateItineraryin the appRegeneratethat dayTraveller movesone activityBack to the constraint setfor those days only

Scroll to pan

The validator is the whole trick. Generation is constrained before it runs and checked after, and an edit re-plans only the days it touched instead of regenerating the trip.
03

The expense ledger

Expense as paidARS, USD, EURRate at timeof spendLedger entryimmutableSplit acrosstravellersSettlementBudget andspend analytics

Scroll to pan

Each entry keeps the currency actually paid and the rate at the time of spend, and every total is recomputed from the ledger rather than kept as a running sum — so history does not drift when rates move.
04

A mutation with no signal

on reconnectnoyesEdit made offlineclient queue, pending in the UIKey alreadyapplied?Apply onceReplay thefirst resultPostgres

Scroll to pan

Trips get edited on planes. The queue holds the write, the UI admits it is pending, and the idempotency key is what stops a reconnect from booking the same hotel twice.
04

Screens

2 captures
TripBox hub showing upcoming trips with countdowns
01The hub — trips with countdowns over the 3D globe
TripBox discovery surface for venues, spots and activities
02Discovery — the curated catalogue, browsable by type
05

Modules

10 units
01

Trip & itinerary

The spine of the product: a trip is destinations across dates, and an itinerary is what actually happens on each of them.

  • Day boards turn a date range into plannable units
  • A master timeline reconciles transport, stays and activities
  • Day trips nest a smaller plan inside a larger one
  • Per-day checklists and events
02

Destinations

A curated database of places, plus the discovery surfaces that turn browsing into an actual plan.

  • Venues, spots and activities as first-class records
  • City guides and editorial destination content
  • Search, explore and discover surfaces
  • A save-to-trip layer that bridges discovery and planning
03

Transport & stays

Everything that moves the traveller or houses them, modelled properly rather than as free text.

  • Flights with explicit layover modelling
  • Accommodation, rentals and tours
  • Distance and travel-time calculation between points
  • Booking records with document storage
04

Cost & budget

A three-layer budget system where the numbers have to be trustworthy enough to replace a spreadsheet.

  • Expenses stored in the currency actually paid, with the rate at the time
  • Cost splitting across travellers
  • Settlement between companions at the end of a trip
  • Budget allocation and spend analytics
05

AI planning

Claude generates the itinerary, and a validation pipeline stops it producing plans that only work on paper.

  • Day-by-day generation constrained by opening hours and travel time
  • Re-planning on change instead of regenerating from scratch
  • Trip import from external sources
  • Recommendation and city-intelligence surfaces
06

Maps & 3D globe

Two levels of geography: a Three.js globe for the shape of a journey, Mapbox for the street it happens on.

  • Interactive globe as the logged-in home surface
  • Mapbox GL for street-level detail and routes
  • Marker clustering across the venue catalogue
  • Route visualisation between destinations
07

Agency console

The B2B layer: travel agencies and DMCs running their client-facing business inside TripBox, under their own brand.

  • Branded client-facing storefronts per agency
  • Client, lead and commission management
  • Payment plans and DMC settlement
  • Argentine tax handling, including percepciones
08

Collaboration

A trip is usually a group activity, so permissions, notifications and shared state are core rather than optional.

  • Invitations with per-trip permissions
  • Notifications and activity feeds
  • Gamification — challenges, badges, leaderboards
  • Social and profile surfaces
09

Offline-first sync

People plan trips on planes and in places with no signal, so mutations survive a dead connection.

  • Server-side idempotency wrapper on mutations
  • Pending-sync state surfaced in the UI
  • Conflict-safe edits
  • Installable PWA with offline routes
10

MCP server

TripBox exposes itself to AI assistants as a set of typed tools and resources — the product is agent-addressable, not just a website.

  • Registers agent tools and resources with typed output schemas
  • An assistant can read and write real trips
  • Same surface I use to plan from a chat window
  • Scoped to the authenticated user
06

Engineering

What was hard
01

AI output that survives contact with reality

A generated itinerary is worthless if it schedules a museum at 3am or teleports you across a city in ten minutes. The generation pipeline constrains Claude with opening hours, real travel time between points and traveller preferences, then validates the result before it ever reaches the UI — and re-plans on change instead of regenerating the whole trip.

02

One design system, two audiences

The consumer app and the agency console share a single language. That constraint is written down in a product brief the code is checked against, because the easy failure mode is a beautiful traveller app bolted to a grey enterprise panel.

03

Money that stays honest

Expenses are stored in the currency actually paid with the rate at the time of spend, so historical totals do not drift when rates move. Splitting and settlement are computed from that ledger rather than from a running total, which is what makes the numbers trustworthy enough to replace a spreadsheet.

04

Mutations that survive no signal

Trips get edited on planes. Mutations go through a server-side idempotency wrapper and a client queue, so a retry after a dropped connection does not double-book a hotel or duplicate an expense.

07

AI harness

9 pieces

TripBox is built with its AI harness committed to the repository. The product identity, the design system and the safety rails are machine-readable, the agents that touch the code are specialised by role, and design findings are re-verified against the source before anyone acts on them.

01Context

Machine-readable product brief

PRODUCT.md defines the register, both audiences, brand personality, explicit anti-references and design principles. DESIGN.md carries the token spec — an OKLCH palette, type ramps, spacing. An agent designing a surface reads the same brief a designer would be handed, so output stays on-brand without me re-explaining it every session.

  • PRODUCT.md
  • DESIGN.md
02Agents

Nine specialised subagents

code-reviewer, test-runner, refactorer, db-migrator, bug-fixer, seed-curator, pr-creator, feature-builder and visual-tester. Each has its own brief and tool scope, so a migration agent cannot wander into UI work and a reviewer cannot quietly rewrite the thing it is reviewing.

  • client/.claude/agents/
03Agents

Thirteen role briefs

tech-lead, frontend-lead, backend-lead, security-lead, qa-engineer, ux-specialist, content-lead, domain-expert, mapbox-specialist, marketing-seo and documentation roles. These are perspectives rather than executors — they define what a given kind of reviewer should care about before it reads a line of code.

  • client/.claude/workers/
04Skills

Project skills, with a lockfile

Bespoke skills for the repetitive work — seo-content-country, seo-content-trip, migrate-db, spec-epic — authored against a shared template so new ones stay consistent. External skills are pinned in skills-lock.json by source and SHA-256, so a third-party skill cannot change under me between runs.

  • client/.claude/skills/
  • client/skills-lock.json
05Skills

Design pass on a post-edit hook

A design-critique skill is wired to fire after every edit, create and patch through a postToolUse hook, with a live browser session for iterating on a surface in place. Design review happens as code is written rather than in a separate round nobody schedules.

  • .github/hooks/impeccable.json
  • .github/skills/impeccable/
06Verification

Adversarial verification passes

Nine verification groups where every reported defect is re-checked against the actual source: confirmed or downgraded, with file, line, and a written reason. A P1 accent-drift claim gets demoted to P2 when it turns out to be purely aesthetic. It is the step that keeps AI review from generating confident noise.

  • verify-trip-builder.json
  • verify-pipeline.json
  • verify-dashboard.json
07MCP

MCP in both directions

The Supabase MCP server lets an agent read the real schema instead of guessing at it. In the other direction, TripBox ships its own MCP server so an assistant can operate real trips — the product is a tool an agent can use, not just a site a human clicks.

  • .mcp.json
  • client/modules/mcp/
08Guardrails

Guardrails written as rules, not hopes

CLAUDE.md opens with a table of forbidden database commands and their safe alternatives, a hard ban on native browser dialogs, and a rule that every image must be uploaded to Storage — with a validate step that fails on any external image URL, because that failure had already shipped blank cards to production twice.

  • client/CLAUDE.md
09CI

Typecheck and migration gates

GitHub Actions run typecheck and check database migrations on every push, with a separate workflow for pushing them. Agents move fast; CI is what makes that safe rather than reckless.

  • .github/workflows/
08

Stack

11 entries
  • 01Next.js
  • 02React 19
  • 03TypeScript
  • 04Supabase
  • 05Claude AI
  • 06Mapbox GL
  • 07Three.js
  • 08TanStack Query
  • 09Remotion
  • 10Playwright
  • 11Vitest