Roadmap
CityScout Build Thread / Part 3 of 4
Extending CityScout to Web: Multi-Surface Product Design
The web version of CityScout isn't meant to replace the iOS app. It's there to widen where planning can happen and where a trip can be reviewed, shared, or resumed — iOS stays the in-trip companion.
Reading note
A clearer write-up of the product thinking, system choices, and tradeoffs behind the build.
In this post
Web should help shape the trip. iOS should help you live it.
Why Add Web At All
A web surface makes sense when the product needs a larger planning canvas. People often research travel across tabs, share plans with other people, or revisit details from a desktop before they leave. Web is a better fit for that kind of work than a phone-only interface.
That doesn't make web the primary experience — it makes it the planning and sharing layer. The trip itself still belongs on iOS, close to maps, quick decisions, and the on-the-ground rhythm of moving through a city.
One Contract, Multiple Surfaces
A shared API contract is the right anchor for multiple surfaces. The iOS app and the future web app should both speak to the same itinerary and guide shapes, so the product does not fork into two subtly different versions of the same trip.
If the web layer lands, I would want the schema, validation rules, and endpoint behavior to stay aligned across clients. Whether that lives in a monorepo or another shared workspace shape is a future decision, but the architectural direction is clear: keep the contract central and avoid duplication.
Security Gets Harder In The Browser
Browser clients raise the security bar. Shared secrets get harder to protect, the surface area for abuse grows, and auth, rate limiting, and response shaping all need more care. It's another reason the AI boundary needs to stay on the server.
- Never expose model credentials to the browser.
- Treat client requests as untrusted until validated on the server.
- Prefer explicit auth and rate limits over optimistic assumptions.
- Keep the itinerary contract stable enough that clients do not need special logic for every endpoint.
Why TDD Matters More Here
Once a product has multiple surfaces, tests stop being optional polish. They become the easiest way to keep the contract honest while the UI evolves. The web layer should not move the system faster than the tests can describe it.
The direction I want to keep tightening is straightforward: test the contract, test the failure modes, and keep the product production-ready before expanding the surface area again. That's how the web layer adds value without adding confusion.