← Work

Suttru

A daily companion for travellers in Tamil Nadu that talks, reads signs and menus, and finds the way, and keeps working when a key or the network is missing

Role
Sole designer and builder
Status
Live
Period
Sep–Oct 2026

Next.js 16 · React 19 · TypeScript · Claude · Sarvam AI · mapbox-gl · Three.js · OSRM · Overpass · Zod · Bun

Problem

Suttru (சுற்று) is for visitors to Tamil Nadu who do not speak Tamil, from other Indian states and from abroad. Its tagline is "Tamil Nadu, told by locals".

It started as a guidebook. Once I used it on the ground I found it was not useful enough: a guidebook is something you read before a trip, and the problems a visitor has are in the moment. A menu you cannot read. A driver who does not understand the station you need. A fare that might be fair or might not. So in October 2026 it became a daily companion, and every feature has to pass one test: does someone open this more than once a day because something is in their way?

Constraints

  • Every feature degrades. Each API route returns 501 when its key is missing, and the client falls back to something that still works offline. The project's own rule: no API keys needed to run it.
  • Facts travellers act on need a source and a date. Prices, hours and fares are either sourced or labelled as estimates.
  • No accounts. Saved places, language and city live in the browser. Photos sent to the reader are never stored. Analytics are cookieless and carry no free text.
  • Free infrastructure where possible. Routing, geocoding and transit stops come from open services, with paid providers only as optional upgrades.

Architecture

PWA shell
Today, Explore, Talk, Ask, Trip
Service worker
network-first, offline page
Route handlers
501 without a key
Claude
Ask, sign reader
Sarvam
speech, translation, voice
OSRM, Overpass
routes, geocoding, stops
Content in data/
typed, sourced, dated
Browser storage
no accounts
Each AI feature has an offline floor underneath it

Content is typed TypeScript, not a CMS: places, phrases, dishes, fares, seasons, each with a source and a checked date. A phone gets five tabs, and eight pocket tools open as a sheet from the URL, so every state has a shareable link.

Ask Suttru. The client posts a question with a 25 second timeout. The server validates it, then calls Claude with a frozen system prompt and the place catalogue as JSON, marked for prompt caching, and asks for structured output. Per-request context goes in the user turn so the cached system prompt stays byte-identical. Any place or experience the model returns is checked against the catalogue on the server, and anything not in it is dropped. If the route returns 501, fails or times out, the client switches to an on-device keyword guide for the rest of the visit.

The sign and menu reader. A photo is shrunk to 1,600 pixels on the phone and sent to Claude's vision model, which returns a typed reading: what kind of sign it is, translated lines, and for menus each dish with a vegetarian flag and price.

Talk. Speech goes to Sarvam's Saaras for transcription, Mayura for translation into colloquial Tamil, and Bulbul for the spoken reply. The speech endpoint is a cacheable GET that answers range requests, and the service worker serves byte ranges itself because Safari insists on them.

Getting around. Every directions button opens an in-app route view that compares auto or cab, metro and train, bus, and walking. The rail planner allows at most one change of train, a walk of up to 1.2 km or an auto of up to 7 km to a station, and rejects any plan whose auto legs are longer than two thirds of the ride.

Key decisions

  1. The model recommends; it does not invent. The system prompt forbids inventing prices, opening hours or phone numbers, and the server only accepts IDs it already knows. The cost is that Ask can only recommend what is curated.

  2. Pick models by how they behave on real Tamil. Sarvam's dedicated translation model is used for one job only, rendering place names in Tamil script. It is not used to translate Tamil back for the visitor, because it mistranslated colloquial speech: "சாப்பாடு முடிஞ்சு போச்சு", roughly "the food has run out", came back as "I'm feeling a bit off".

  3. Show both fares. For autos, the app shows the official 2013 Chennai tariff alongside the higher rates drivers' unions actually charge, both labelled as estimates. One number would be cleaner and wrong.

  4. Honest padding on free routing. OSRM has no traffic data, and autos and cabs average about 20 km/h in Tamil Nadu's cities by day. So a drive takes whichever is longer: OSRM's time plus 20%, or the first 40 km at 20 km/h. When a Mapbox token is present, traffic-aware routing takes over.

  5. Rail is a snapshot, not live. Five lines and 98 stations are bundled from OpenStreetMap. Chennai Metro Phase 2 is left out because its stop order in OSM is scrambled, and a wrong stop order is worse than a missing line. Tamil station names come from OSM, then from the same station on another line, then from Sarvam, with hand overrides.

  6. Back closes things. Dialogs, sheets and the phone map are history entries, so the back button closes them instead of leaving the app.

What broke

  • A review pass fixed ten bugs in one PR, including the back stack, the mic starting twice, GPS overriding a chosen city, iOS audio, retrying 4xx errors from Sarvam, and duplicate sends at the 25 second mark.
  • iOS audio. Audio only plays if it is unlocked synchronously inside the tap that starts it, and Safari needs 206 partial responses, which the service worker now produces.
  • A bad key looked like an outage. A rejected Sarvam key returned 401 or 403 to the client. It now maps to 501, so the app falls back to offline phrases instead of showing an error.
  • Overpass is often busy. Transit stops try three mirrors twice within a 25 second budget. First loads in a new area can still take 10 to 25 seconds.
  • A security fix forced a framework jump, from Next.js 15.5.4 to 16.3.4, mid-build.

Results

Live, with 23 commits between 8 September and 11 October 2026. It covers four cities with 36 curated places, 107 phrases, 60 dishes, and Talk in Tamil plus ten other languages, and has 51 unit tests.

What I'd change

  • Native-speaker review. The phrases, dishes and daily content were written with AI and have not been checked by a native Tamil speaker yet. For a product whose tagline is "told by locals", that comes first.
  • A shared store for limits and caches. Rate limits and caches live in memory, which is fine on one instance and wrong on many.
  • Live transit. The rail snapshot is honest but static. Live departures for metro, suburban rail and buses would turn route options into actual plans.
Next case studyNearbyLens →