Work / App Prototype
Travel Intelligence IQ: a travel briefing that shows its working
Travel Intelligence IQ turns an itinerary into a source-linked operating brief for a business trip. It brings flights, meetings, route buffers, weather, local conditions and warnings into one view, keeps useful sections available when a provider fails, and shows where each result came from.
Demonstration data. Invented data.
At 08:27 the screen tells me to leave the hotel. It has allowed 18 minutes for the journey, added a preparation buffer and put the first workshop beside the weather warning that could disrupt it. One provider has reached its limit, but the rest of the briefing is still there. I can see what is current, what is unavailable and where each result came from.
Travel Intelligence IQ turns a business-trip itinerary into an operating brief, not another list of bookings. It answers three questions: what I need to know next, what has changed and which source supports the answer.

At a glance
- Status: Prototype. A hosted build exists and the product has been through structured user acceptance testing.
- Built: August to September 2026.
- Platform: responsive progressive web app for desktop and mobile.
- Stack: React, Vite, TypeScript, Hono, Cloudflare Workers and Workflows, Supabase Auth and Postgres, Playwright.
- Built with: Claude Code, working from a detailed engineering specification, task packets, decision records and test evidence.
- AI inside the product: yes. Anthropic is used for two bounded jobs: proposing itinerary entries from a user-selected travel document and assessing public travel news against a reduced trip context. The core itinerary, alerts and briefing remain usable without it.
The trip as an operating plan
The first view answers four practical questions: when should I move, how long should it take, what conditions matter and how busy is the trip? A readiness score sits beside those answers, with a plain reason when a source or location needs checking.
On a phone the same hierarchy becomes a compact sequence rather than a reduced desktop page. The buttons remain large, the route and weather figures stay readable, and the warning board follows immediately below the summary.

The Work area turns meetings into a calendar and places the route plan beside it. Each leg carries a leave-by time, travel estimate, arrival target and preparation buffer. Airport transfers are kept separate because their uncertainty is different from a journey between the hotel and a meeting.

The itinerary itself keeps source bookings and operational documents together. Flights and stays are shown as timed entries, while boarding passes and fast-track documents sit in a private travel wallet. The wallet is not a public share area. Files are accessed through the Worker after a trip-ownership check, rather than through an open browser storage policy.

Text walkthrough of the captured journey
- Open the Copenhagen briefing and read the readiness score, leave-by time, journey estimate, weather and meeting count.
- Review the critical wind warning and the dismissible rain recommendation. Open the evidence explanation if needed.
- Move to Work to see the meeting calendar and the ordered hotel-to-workshop and workshop-to-studio route plan.
- Move to Travel intelligence to see the three-day forecast and the explicit news-provider failure.
- Return to Overview and expand the source ledger to see which sections are available and which one failed.
A briefing that survives a failed provider
A travel briefing depends on several outside services. Weather can succeed while news is rate-limited. A route may be available while an event source has no coverage for that city. Treating that as one all-or-nothing request would make the whole product fragile.
Build decision. Each section has its own state: available, partial or unavailable. The workflow can publish an immutable partial briefing, so a failed provider does not erase the useful work completed by the others.
The briefing makes the news failure visible. It does not fill the gap with generic text, quietly omit the section or pretend the last answer is current. Weather remains usable, with its retrieval time, while news says that the provider limit was reached.

That behaviour continues into the source ledger. Every section records whether it is available and, when present, the provider response that produced it. The interface translates the technical state into plain labels: itinerary, weather, journey times, near the hotel, news and events.

Every published briefing is tied to an immutable itinerary version rather than whatever happens to be in the edit screen later. If I correct a flight or move a meeting, the next generation can be compared with the previous published version instead of silently rewriting the basis of an old answer.
Alerts are rules first, AI second
The Immediate attention board looks like the most intelligent part of the interface, but its most important warnings are deterministic. Weather thresholds, transfer buffers and coverage gaps produce explainable alerts with stable rule identifiers and evidence references. A critical alert cannot be dismissed. A lower-severity recommendation can be dismissed without deleting the evidence behind it.
Build decision. AI is not allowed to create an unsupported critical warning. Critical severity requires evidence that the local rule set has explicitly authorised.
The provider-neutral AI gateway enforces the same boundary. It can use OpenAI or Anthropic structured output, but the model receives bounded, already-normalised evidence rather than raw booking data. Every recommendation has to cite an evidence identifier supplied with the request. Unsupported references, malformed output and absolute safety claims fail validation.
In the current product, Anthropic has two narrow jobs. A traveller can choose a PDF and ask the system to propose flight and hotel entries. Separately, the system can assess public news against the destination, travel dates and generic commitment times. The news request excludes meeting names, addresses, booking references and the internal trip identifier. For document import, the interface tells the user to upload only relevant booking pages and not identity or payment documents. Both features are controlled by an administrative switch.
Inside the system
The browser never talks directly to Supabase Auth. It submits credentials and callback codes to the same-origin Worker, which validates tokens and holds them in HttpOnly cookies. That keeps the token out of browser JavaScript and puts origin checks, refresh behaviour and cookie policy in one boundary.
Supabase still enforces row level security on every exposed table. The Worker and workflow have server-only credentials for the jobs that need them, while the browser gets neither a service credential nor direct privileged access. Provider keys are Worker or Workflow bindings, not frontend configuration.
| Layer | What I used |
|---|---|
| Interface | React and Vite in TypeScript, a responsive progressive web app |
| API | Hono on Cloudflare Workers, same-origin, with HttpOnly cookie sessions |
| Durable jobs | Cloudflare Workflows publishing immutable briefing versions |
| Data and auth | Supabase Auth and Postgres with row level security on every exposed table |
| Integrations | Weather, route, news and event providers behind a provider-neutral gateway |
| Runtime AI | Anthropic (document import and news assessment), checked against cited evidence |
| Hosting | Cloudflare |
| Test tooling | Playwright, plus the recorded task-packet evidence |

Offline behaviour follows the same boundary. The last published briefing can be cached for a trip and shown with a clear stale/offline strip when live requests fail. Mutation controls are disabled in that state. A downloaded snapshot is read-only and recursively removes booking, confirmation, ticket, reservation, PNR and record-locator fields. Signing out clears the browser cache.
Built in numbered packets
Thirty-two numbered task packets turned the engineering specification into bounded pieces of work. Each packet records scope, evidence, test results and known limitations. I built Travel Intelligence IQ with Claude Code as a React and TypeScript progressive web app on Cloudflare Workers and Supabase, working through those packets one at a time. Architecture decisions define the Supabase boundary and Worker-managed sessions, while the beta assessment keeps release readiness separate from code completion.
User acceptance testing shaped the interface. Early itinerary entry assumed airport codes and specialist time-zone knowledge. The correction pass added searchable airports, inferred destination time zones, one entry per flight leg, safe editing, overnight-return tolerance and server-side address search with manual entry as a fallback.
What it shows
Treating missing information as data changed the whole product. Once availability, freshness and provenance became first-class fields, the interface could be honest without becoming unusable. A partial briefing could still answer the next practical question, and the source ledger could show exactly where confidence ended.
A narrow product boundary also makes AI governance concrete. The application computes the itinerary, route plan, thresholds and evidence set. The model is asked to assess or propose within that frame, and its output is checked before it becomes part of the product. That is more useful than asking a model to be cautious in a prompt and hoping the instruction holds. Travel Intelligence IQ shows that a briefing can stay honest about what it knows: every section carries its state and its source, and AI contributes only inside boundaries the application sets.