17 KiB
Roadmap: araharah
Overview
araharah turns Telegram into a privacy-respecting turn-by-turn navigator for KL: a bot handles
identity, search, and launch; a Telegram Mini App renders Rams-styled route guidance; Valhalla
routing, self-hosted Photon lookup, OpenFreeMap tiles, and MapLibre GL JS v6 supply the OSM
geodata layer; one Cloudflare Worker (static assets + webhook + /api/*) serves it all with
KV-only TTL storage. The roadmap follows the research's strict dependency funnel — design tokens
first (design fidelity is the flagged #1 sink for v1), then the bot/identity security floor,
then the Mini App shell with geolocation, then KL destination search, then routing and route
display, then live turn-by-turn guidance including backgrounded chat turn-cards, and finally a
hardening pass that earns the private launch. Two phases deliberately surface the project's
biggest unknowns early: WebView geolocation quirks (Phase 3) and KL search quality (Phase 4).
Phases
Phase Numbering:
- Integer phases (1, 2, 3): Planned milestone work
- Decimal phases (2.1, 2.2): Urgent insertions (marked with INSERTED)
Decimal phases appear between their surrounding integers in numeric order.
- Phase 1: Design Tokens + Rams Foundation - Distill the Telemetry Rams system into a single token package and Rams-styled map basemap, with a mockup-vs-implementation approval artifact — before any screen is built
- Phase 2: Bot Skeleton + initData Security - grammY bot on one Cloudflare Worker: /start, command menu, /privacy, and HMAC-validated identity with TTL-only KV storage
- Phase 3: Mini App Shell + Geolocation - Telegram WebApp shell that boots, authenticates, and reads a reliable live location across the Android/iOS/Desktop client matrix
- Phase 4: Destination Search + KL Gazetteer - Free-text KL search that resolves landmarks despite Malay abbreviations and typos, venue cards, and Mini App launch with destination preloaded
- Phase 5: Routing + Route Display - Valhalla-backed route calculation shown as a Rams route line with quiet alternative cards; the full search→route→render loop lands
- Phase 6: Turn-by-Turn Guidance (Live Driving) - Client guidance state machine: maneuver banner, missed-turn auto-recalculation, honest ETA, haptics, seamless resume, and backgrounded chat turn-cards
- Phase 7: Hardening + Private Launch - Device-matrix QA, graceful failure states, privacy-by-construction audit, and golden-route regression before real drivers
Phase Details
Phase 1: Design Tokens + Rams Foundation
Goal: The Telemetry Rams design system exists as one centralized, importable token set — including map basemap cartography — with a user-approved mockup-vs-implementation gallery proving the fidelity bar before any product screen is built. Depends on: Nothing (first phase) Requirements: DSGN-01, DSGN-02 Success Criteria (what must be TRUE):
- Every rendered Rams component derives exclusively from the centralized token set (exacted palette, 8px grid, radius-0, typography) — an audit sweep finds zero off-token color/spacing/typography values in the component sheet (DSGN-01)
- A side-by-side gallery comparing the rendered token/component sheet against the
stitch_minimalist_route_navigator/mockup screens exists and is approved by the user — establishing the DSGN-02 approval artifact mechanism reused by every later UI phase - A Rams-styled MapLibre basemap (OpenFreeMap
libertystyle forked to Rams tokens: grayscale grounding, muted land/water, prepared accent for route highlighting) renders in a browser (DSGN-01, map cartography) - Design authority is singular: the duplicate inline Tailwind token blocks and the conflicting root
DESIGN.mdtypography are superseded by the token package as the one source of truth (resolves the CONCERNS.md design-source conflict) Plans: 4 plans
Plans:
- 01-01-PLAN.md — Repo hygiene + Tailwind v4 token package (
theme/) + self-hosted fonts + DESIGN.md supersession (D-01/02/04/05/06/07/16) - 01-02-PLAN.md — Component sheet:
theme/src/components.css+sheet.htmlconsuming tokens only (D-03/D-11) - 01-03-PLAN.md — Rams basemap: token-derived OpenFreeMap liberty fork + KL preview (D-08/09/10)
- 01-04-PLAN.md — Off-token audit (D-13) + Playwright captures (D-14) + DSGN-02 approval gallery (D-12), blocking user checkpoint
Notes:
- Repo hygiene lands here first: scrub
*:Zone.Identifierartifacts,.gitignorefor OS junk/node_modules/secrets (pre-dates any credential handling). - Project skill
.agents/skills/design-taste-frontend/applies to all UI phases under its existing brand/design system special case: keep the Rams palette/type, app-screen house rules for dashboard-like surfaces, real-browser inspection for the gallery artifact. Telemetry Rams tokens are binding where skill defaults would differ. - Standard patterns (no research phase needed): mockups are the spec; token extraction from the mockup Tailwind config. UI hint: yes
Phase 2: Bot Skeleton + initData Security
Goal: Users can reach araharah through Telegram with a working command surface, and the backend's identity + privacy architecture is provably sound from the first deploy — the initData validator is the first backend artifact. Depends on: Phase 1 Requirements: ONBD-01, PRIV-01, PRIV-02 Success Criteria (what must be TRUE):
- A new user sends /start and receives a concise explanation plus an always-available command menu (/help, /privacy) that answers correctly (ONBD-01)
- /privacy gives an honest, visible statement of what araharah stores and does not store (PRIV-01) — the in-app "trip ended, data deleted" messaging half completes with guidance in Phase 6, riding this requirement's message design
- Tampered, stale, and replayed initData payloads are rejected with CI test vectors and known-good HMAC cases passing; only validated identities receive a one-time session token (security gate — the phase's exit criterion)
- A storage spot-check shows KV with TTL-only namespaces and zero persistent coordinates or user profiles — privacy by construction holds from the first line of backend code (PRIV-02; re-audited in Phase 7) Plans: TBD
Notes:
- One Cloudflare Worker deployable (static assets + webhook +
/api/*); KVchat_sessions(minutes TTL) is the first namespace; theguidance_sessions(~2h TTL) envelope is only designed with its consumer in Phase 5. - Standard patterns (no research phase needed): grammY + Workers hosting is first-class documented; verify exact grammY initData typings at phase start (research gap). UI hint: no
Phase 3: Mini App Shell + Geolocation
Goal: The Mini App opens inside Telegram, establishes a validated session, and obtains the user's live location reliably — with every fallback path that keeps location flowing when the primary path dies, verified on real devices. Depends on: Phase 2 Requirements: GEO-01, GEO-02, GEO-03, PX-02 Success Criteria (what must be TRUE):
- On a real Android phone and iOS phone, the user grants location and sees their live position rendered on the Rams basemap; the permission grant persists across session restarts via LocationManager (version-gated) (GEO-01)
- When in-app location fails (Desktop Telegram without geolocation, or denied permission), the chat "send location" keyboard fallback recovers the origin and the app proceeds with it (GEO-02)
- Location denial shows a deliberate denied state (never a blank map), and the app renders correctly under Telegram light and dark themes while the map keeps Rams cartography constant (PX-02, platform themes)
- No coordinate written anywhere persists: storage remains TTL-ephemeral only, spot-checkable at phase exit (GEO-03)
- Device-matrix exit pass: Android + iOS + Desktop + plain browser each demonstrate boot → session → position, exercising the full fallback chain (pitfall research device-matrix criterion) Plans: TBD
Notes:
- Highest platform-integration uncertainty in the project — research recommends
/gsd-research-phase(Android LocationManager stale-fix workaround,getLiveData()wrapper, WebView permission bridges, browser testing harness). - BackButton wiring and safe-area groundwork are built here as shell infrastructure; the observable PX-01/PX-03 behaviors are claimed by Phase 6 where the full state graph exists. UI hint: yes
Phase 4: Destination Search + KL Gazetteer
Goal: Users type a destination the way locals actually write it and get the right KL-metro landmark back, then step into the Mini App already aimed at their destination. Depends on: Phase 3 Requirements: SRCH-01, SRCH-02, SRCH-03, ONBD-02, ONBD-03 Success Criteria (what must be TRUE):
- Typing "KLCC" — plus the golden query set ("Sunway Pyramid", "DUKE", mall and kampung-style queries) — returns the right KL landmark in a shortlist (SRCH-01)
- Abbreviated, typo'd, and missing-space queries ("Jln Ampang" ↔ "Jalan Ampang", "Tmn", glued words) resolve to the same result as the canonical spelling (SRCH-02)
- Choosing a result sends a native venue card in chat confirming the destination before navigation opens (SRCH-03)
- Tapping through from the search result launches the Mini App with the destination preloaded — no re-entry in the webview (ONBD-02); adding araharah to the phone home screen and launching from there lands in the app ready to search (ONBD-03)
- The self-hosted Photon KL bake-off is concluded against the real-query acceptance corpus with the decision (and any gazetteer/fallback escalation) documented — the search-quality experiment closes, it doesn't stay open Plans: TBD
Notes:
- Budgeted bake-off: research recommends
/gsd-research-phase(gazetteer sourcing/structure ~200 entries, Malay normalizer, photon-vs-fallback decision; funds a GraphHopper MY dump on the VPS). - VPS provisioning (Photon + Valhalla hosting) begins here — free-first infrastructure mandate (Oracle Cloud Always Free candidate). UI hint: no
Phase 5: Routing + Route Display
Goal: The product exists end-to-end: current location to Rams-drawn route with quiet alternative choices, on routing infrastructure fast enough for the guidance phase to build on. Depends on: Phase 4 Requirements: RTNG-01, RTNG-02 Success Criteria (what must be TRUE):
- A user sees their calculated route drawn on the Rams-styled map — grayscale basemap grounding with the accent route line — from their current location to the chosen destination (RTNG-01)
- The user can choose among up to 3 alternatives presented as quiet Rams cards (time, distance, one-line difference) and the selection redraws (RTNG-02)
- The golden-route corpus (10–20 real KL origin/destination pairs) routes cleanly through self-hosted Valhalla (Malaysia extract) behind the Worker proxy — no dead ends, no geometry failures, latency and Worker subrequest budgets holding with instrumentation visible Plans: TBD
Notes:
- GUID-05/06 upstream design obligations land here deliberately: the route model carries step geometry + snapped-progress support from day one, and the ephemeral
guidance_sessionsKV envelope (id, chat ref, route snapshot ref, ~2h TTL) is designed here so the backgrounded turn-card service in Phase 6 has its session contract already defined. - Standard patterns (no research phase needed): documented preprocess pipeline for Valhalla + the graph/tiles build; no exotic APIs. UI hint: yes
Phase 6: Turn-by-Turn Guidance (Live Driving)
Goal: While driving, araharah behaves like real navigation — prominent maneuvers, silent self-healing recalculation, honest ETAs, haptic cues, seamless resume — and guidance survives the app being minimized via best-effort chat turn-cards. Depends on: Phase 5 Requirements: GUID-01, GUID-02, GUID-03, GUID-04, GUID-05, GUID-06, PX-01, PX-03 Success Criteria (what must be TRUE):
- During a drive, the user sees a prominent next-maneuver banner (distance + arrow + street name) with a collapsible full maneuver list (GUID-01), ETA and remaining distance progressing with each location fix without visible whiplash (GUID-03), and a haptic cue at maneuver points (GUID-04)
- After a missed turn, the app silently recalculates from the current position — no asking, no blaming — and reroute storms are held back by the debounce/hysteresis state machine (GUID-02, verified via recorded-drive replays plus a real drive)
- Minimizing the app mid-drive switches the bot to pushing chat turn-cards (map snapshot + next maneuver + ETA, best-effort projection) for the remainder of the trip (GUID-05, served by the Phase 5-designed ephemeral guidance session); re-opening mid-trip resumes live guidance seamlessly at the progressed position (GUID-06)
- The Telegram BackButton walks the full app states (search → routes → guidance → back to search) and never dead-ends (PX-01 — full state graph only exists now); closing during guidance requires passing the "abandon route?" confirmation, with safe areas respected and vertical-swipe-close disabled during guidance (PX-03)
- Ending a trip deletes the ephemeral guidance session and shows the "trip ended, data deleted" messaging — completing the in-app half of PRIV-01's promise at the trip boundary Plans: TBD
Notes:
- Highest behavioral uncertainty (reroute triggers, ETA smoothing, battery) — research recommends
/gsd-research-phase(backgrounded turn-card "best-effort projection" framing + static map snapshot generation; product decision needed for what "good enough" means minimized). - Schedule slack budgeted here per research; backgrounded turn-cards are folded into this phase per roadmap instructions with the session contract pre-designed upstream (Phase 5). UI hint: yes
Phase 7: Hardening + Private Launch
Goal: Real KL drivers get an honest, robust experience: every failure state designed, the privacy promise holding under audit, performance within free-tier budgets, and a known-limitations document that tells the truth — then the launch. Depends on: Phase 6 Requirements: PX-04 Success Criteria (what must be TRUE):
- Guidance supports fullscreen and remains usable in landscape (driving posture) across the full real device matrix — Android, iOS, Desktop, browser (PX-04) — folded into the phase's device-matrix QA pass including the battery drain target (<10%/hr during guidance)
- Every empty/error/timeout/off-road/no-geometry state renders gracefully (no blank screens, no broken layouts); version-gating fallbacks behave sanely on older Telegram clients
- Privacy verification passes: an architecture audit shows no persistent per-user location history or profile anywhere — coordinates exist only in TTL-expiring KV, and logs carry no coordinate data (re-verifies PRIV-02, GEO-03 end-to-end)
- The golden-route regression pass is green, Worker budgets audit clean (subrequests/CPU, cache hit-rate), and the "known limitations" doc (OSM data gaps, no traffic confidence, no lane guidance) ships before the first real drivers Plans: TBD
Notes:
- No exclusive feature requirements beyond PX-04 — this phase hardens the outcomes of Phases 1–6 and is the last chance to catch the "looks done but isn't" failures for a navigation tool whose empty states ARE the polish surface. UI hint: no
Requirements Coverage
| Phase | Requirements |
|---|---|
| 1 | DSGN-01, DSGN-02 |
| 2 | ONBD-01, PRIV-01, PRIV-02 |
| 3 | GEO-01, GEO-02, GEO-03, PX-02 |
| 4 | SRCH-01, SRCH-02, SRCH-03, ONBD-02, ONBD-03 |
| 5 | RTNG-01, RTNG-02 |
| 6 | GUID-01, GUID-02, GUID-03, GUID-04, GUID-05, GUID-06, PX-01, PX-03 |
| 7 | PX-04 |
Coverage: 22/22 v1 requirements mapped — no orphans, no duplicates. (PRIV-01's in-app trip-boundary messaging and PX-01/PX-03 groundwork are noted where they're staged, but each requirement maps to its owning phase exactly once.)
v1.x Candidates (post-v1, not roadmap phases)
Per research: voice guidance (gated on iOS WKWebView TTS spike), live trip share via sendLocation(live_period), toll vs toll-free toggle (Valhalla use_tolls), speed-limit display where OSM maxspeed exists. These hang off validated routing + guidance — plan a v1.x milestone after user validation, do not pull into the spine above.
Progress
Execution Order: Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7
| Phase | Plans Complete | Status | Completed |
|---|---|---|---|
| 1. Design Tokens + Rams Foundation | 0/TBD | Not started | - |
| 2. Bot Skeleton + initData Security | 0/TBD | Not started | - |
| 3. Mini App Shell + Geolocation | 0/TBD | Not started | - |
| 4. Destination Search + KL Gazetteer | 0/TBD | Not started | - |
| 5. Routing + Route Display | 0/TBD | Not started | - |
| 6. Turn-by-Turn Guidance (Live Driving) | 0/TBD | Not started | - |
| 7. Hardening + Private Launch | 0/TBD | Not started | - |
Roadmap created: 2026-10-22