Skip to study
EW Studio

2021 → 2026 / Natour

A plan with its feet on the ground.

The AI writes the itinerary. OpenStreetMap checks the places. Unchecked stays visibly unchecked.

Role
Product, design direction and engineering lead, built with Claude Code
Timeline
2021 original · rebuilt 19–25 October 2026
Stack
React 19 · TypeScript · TanStack Router · IndexedDB

Map data © OpenStreetMap contributors / ODbL; place checks by Nominatim; tiles by OpenFreeMap / OpenMapTiles. Guides: Wikivoyage / CC BY-SA 4.0. Climate data obtained from the NASA Langley Research Center POWER Project, funded through the NASA Earth Science Division, Climatology API 2001–2025. Photo credits remain in the source screen.

Capture actions, source links and limits

See the phone layoutNatour live phone interface at 390 pixels wide
1 request / s

Nominatim budget shared by the whole app. Climate uses NASA POWER 2001–2025 monthly averages, not a forecast.

The rebuild

Keep the spark.
Rebuild the product.

2021 → 2026

Natour started in 2021 as three CSS exercises from the same course: natour, a tour-booking landing page whose form went nowhere; Trillo, a hotel page with made-up reviews and "only 4 rooms left"; and Nexter, a homes page that survived only as built files. None of it did anything. What was worth keeping was the travel idea, natour's Easy / Medium / Hard tours, and "where to stay".

Reconstructed from the original 2021 Header component at 2be11cc with compatibility tooling. The Natour, Trillo and Nexter CSS course exercises are credited in the app README. Revision and substitutions

2021 source reconstruction → live 2026 product. Same 1440 × 900 viewport, uncropped. Historical layout rendered with compatibility tooling; it does not demonstrate the old services working.

Natour, live 2026 interface
2026 / live product
Natour, 2021 source reconstruction
2021 / reconstruction

The idea

A journal, a route, a check stamp.

Fraunces on map paper, terracotta route lines and forest-green stamps. The route-line N ends in a pin; a check is earned by a lookup rather than model confidence.

Natour

Fraunces / original SVG mark

Paper / #F4EFE6Terracotta / #B8402AForest / #2C6A4C

Brand colours above; text and focus accents adapt for contrast in each portfolio theme. Design source ↗

Three engineering decisions

The constraint shapes
the implementation.

Check names before adding pins

Constraint. Suggested places can be invented or refer to a road/bus stop

Decision. search Nominatim inside the destination bounds and require at least half the normalized name words to match; exclude inappropriate place types

Result. the recorded Lisbon plan dropped one unmapped suggestion, and accepted stops use OSM names/coordinates. Busy/offline checks preserve a labelled unverified stop without a pin.

Source and evidence limits

natour/README.md → “The AI can't add a place that doesn't exist”, naming src/lib/check.ts. One recorded plan is not an accuracy benchmark.

Read the pinned README ↗

Let data terms choose the stack

Constraint. A planned commercial product cannot assume every free public endpoint fits

Decision. use a shared Nominatim queue at 1 request/second, submit-only search and caching; omit public Overpass/OSRM demo and free Open-Meteo under the documented terms assessment

Result. estimated walking times use straight-line distance ×1.3 at 4.8 km/h, labelled ~; NASA POWER supplies 2001–2025 monthly climate averages instead of a forecast.

Source and evidence limits

natour/README.md → “The terms of each data source shaped the app”, “Data and credits”; natour/docs/data-terms.md → source rows. The terms document confirms NASA POWER is used, approved by the owner on 2026-10-23.

Read the pinned README ↗

Let jobs outlive a React view

Constraint. A plan can still be streaming when a user changes views

Decision. src/lib/trips.ts runs jobs outside React, checks each JSON line and writes to IndexedDB; pages watch live queries

Result. switching views preserves progress and two tabs show the same progress. Closing the running tab still interrupts the job; the next visit clears it with a note.

Source and evidence limits

natour/README.md → “Jobs run outside React”. Two tabs are documented behavior, not evidence of a durable background worker or server job queue.

Read the pinned README ↗

Architecture

Follow one request.

Description01Browser job02Place checks03IndexedDB04Live-query views05DescriptionBrowser jobPlace checksIndexedDBLive-query views
A browser job streams and validates JSON Lines, checks destination-bounded names through the shared Nominatim queue and writes to IndexedDB. Views subscribe with live queries. Wikivoyage supplies guides, NASA POWER supplies climate averages and OpenFreeMap supplies tiles. A stop that cannot be checked is labelled and has no pin. Closing the running tab interrupts its job.

Quality proof / evidence, with scope

Show what was checked.

App evidence

README reports mobile landing performance 0.96–0.98 and 1.0 in the other categories.

Repository report, read 26 October 2026. These app scores were not rerun for this portfolio.

Commands and evidence in the README ↗

This portfolio page

Static HTML, deferred decorative Stage, explicit media intent and complete reduced-motion content.

performance
96/100
accessibility
100/100
best practices
100/100
seo
100/100

Lighthouse mobile, light theme, cold cache, simulated throttling. Measured 2026-10-26. Gzip static export on localhost.

Eight page cases across Chromium/WebKit, phone/desktop and both themes; two axe audits with zero violations. WebKit playback and real Safari hardware remain unverified.

Read the dated portfolio check results ↗

The honest next step

What remains.

Interrupted jobs do not resume after tab closure. Durable resume is a proposed improvement. Natour uses email-code sign-in only.

NASA POWER approval and source terms, 23 October 2026 ↗

Next / Back to the studioFive products. One foundation. ← Back to studio index