From 86739aaa944e9cca3a7c65f728cb3b0047856e58 Mon Sep 17 00:00:00 2001 From: araharah-executor Date: Sun, 25 Oct 2026 13:43:02 +0800 Subject: [PATCH] =?UTF-8?q?wiki:=20Home=20=E2=80=94=20HTML-entity=20the=20?= =?UTF-8?q?confusable=20literals=20(=C2=B2=E2=86=92=C2=B7=C3=97)=20so=20Gi?= =?UTF-8?q?tea's=20ambiguous-unicode=20banner=20clears;=20rendered=20text?= =?UTF-8?q?=20identical?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Home.md | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/Home.md b/Home.md index 254a522..eee0c93 100644 --- a/Home.md +++ b/Home.md @@ -1,10 +1,10 @@

- arah² logo + arah² logo

-# arah² +# arah² A privacy-respecting, Telegram-first GPS navigator — a waze-like route navigator delivered through a Telegram bot and Mini App instead of an app-store install, built on OpenStreetMap data, and designed to Dieter Rams' "less, but better." First users are in the Kuala Lumpur metro. @@ -14,7 +14,7 @@ The Telegram bot is **arah2bot**. The product is live — a private beta with re ## Overview -arah² is an npm-workspaces monorepo with five packages: +arah² is an npm-workspaces monorepo with five packages: | Package | Name | What it does | |---|---|---| @@ -46,7 +46,7 @@ graph TD APP -->|"GET /api/location — Bearer token"| W APP -->|"POST /api/route — Bearer token"| R2 W --> KV - W -->|"cron */2 → turn cards"| TG + W -->|"cron */2 → turn cards"| TG APP --> MAP THEME -.->|"inlined at build time"| MAP THEME -.->|"dist/rams.css"| APP @@ -109,14 +109,14 @@ cp bot/.dev.vars.example bot/.dev.vars --- -## Quickstart: clone → production (your own bot, your own Cloudflare) +## Quickstart: clone → production (your own bot, your own Cloudflare) The concise path. Full detail lives in [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md); local development in [docs/GETTING-STARTED.md](docs/GETTING-STARTED.md). **1. Create the bot** — in Telegram, open [@BotFather](https://t.me/BotFather): -- `/newbot` → pick a name + username → copy the **bot token** -- `/setuserpic` → upload `assets/logo_arah2.png` (the bot's avatar) -- Bot Settings → **Main Mini App** → set your future production URL (you'll fill the real one in step 4; BotFather's app *name* is what Telegram shows in the mini-app header) +- `/newbot` → pick a name + username → copy the **bot token** +- `/setuserpic` → upload `assets/logo_arah2.png` (the bot's avatar) +- Bot Settings → **Main Mini App** → set your future production URL (you'll fill the real one in step 4; BotFather's app *name* is what Telegram shows in the mini-app header) **2. Clone + install** @@ -139,8 +139,8 @@ MINI_APP_URL=https://.workers.dev ```bash npx wrangler login # browser auth, once -npm run build # theme tokens → web/dist -npm run deploy # theme → web → worker + assets + webhook + commands +npm run build # theme tokens → web/dist +npm run deploy # theme → web → worker + assets + webhook + commands ``` **5. Provision the road graph** (engine A's routing data — R2, also free): @@ -155,7 +155,7 @@ node routing/scripts/upload-road-graph.mjs # builds + uploads the KL graph, ro ```bash node bot/scripts/set-webhook.mjs # arms the webhook (+ /telegram/webhook path) node bot/scripts/register-commands.mjs # /help /privacy /cari in every command scope -node bot/scripts/set-menu-button.mjs # the menu button opens the app ("arah²") +node bot/scripts/set-menu-button.mjs # the menu button opens the app ("arah²") ``` **7. Verify** — the canaries (read-backs, nothing trusted blindly): @@ -163,9 +163,9 @@ node bot/scripts/set-menu-button.mjs # the menu button opens the app ("arah ```bash npm run privacy-audit -- --live && npm run budget-audit -- --live ``` -Then in Telegram: restart the client → open the bot → `/cari KLCC` → venue card → **OPEN** → the map routes. Done: your own private navigator, $0/month. +Then in Telegram: restart the client → open the bot → `/cari KLCC` → venue card → **OPEN** → the map routes. Done: your own private navigator, $0/month. -> **Permission notes:** the Cloudflare token (optional, only for the audit `--live` probes) needs Account → Workers KV Storage → **Read** only. The bot itself needs no special Telegram permissions; `/setprivacy` default (off) is correct — the bot never reads non-command messages. +> **Permission notes:** the Cloudflare token (optional, only for the audit `--live` probes) needs Account → Workers KV Storage → **Read** only. The bot itself needs no special Telegram permissions; `/setprivacy` default (off) is correct — the bot never reads non-command messages. --- @@ -176,7 +176,7 @@ Then in Telegram: restart the client → open the bot → `/cari KLCC` → venue - **WASM-router track** — fully client-side routing in the webview (origin+destination never touch a server; static-hosted; the fork-perfect endgame) - **Battery measurement** — the <10%/hr guidance-drain record (deferred from launch) - **Bitmap map snapshots** in minimized chat turn-cards (needs a rasterizer in the $0 stack) -- **Voice guidance** · **live trip share** (`sendLocation(live_period)`) · **toll toggle** · **speed-limit display** — the REQUIREMENTS deferred table +- **Voice guidance** · **live trip share** (`sendLocation(live_period)`) · **toll toggle** · **speed-limit display** — the REQUIREMENTS deferred table **v2 (post user-validation):** - Incident reports + community layer, gamification, traffic-weighted ETAs — per the original vision doc ([IDEAS.md](IDEAS.md)) @@ -195,7 +195,7 @@ The bot answers in English and Bahasa Melayu. Commands are registered into Teleg | Command | Alias | Behaviour | |---|---|---| -| `/start` | `/mula` | One-sentence introduction to arah² and its privacy posture. | +| `/start` | `/mula` | One-sentence introduction to arah² and its privacy posture. | | `/help` | — | Lists the commands that exist and points at the known-limits record. | | `/privacy` | `/privasi` | Names exactly what is stored (user id, chat id, language, ~15 min) and exactly what is never stored (location, routes, trip history, profile). | | `/cari` | `/search` | Searches the curated KL gazetteer (`/cari KLCC`) and replies with **one** native venue card (`sendVenue`) carrying an OPEN IN ARAHARAH Mini App button plus 2–4 alternates as callback buttons. Out-of-area queries get an honest refusal that names the v1 area, never the query text. | @@ -204,7 +204,7 @@ The bot answers in English and Bahasa Melayu. Commands are registered into Teleg 1. **Search.** `/cari ` normalizes and scores the query against the KL gazetteer (`@araharah/search`); the best hit ships as a venue card with deep link `MINI_APP_URL/?dest=`. 2. **Open the Mini App.** The webview reads `?dest=` from `location.search`, preloads the destination, and mints a session by posting the verbatim `Telegram.WebApp.initData` string to `/api/session`. -3. **Acquire a starting point.** The three-link location chain (`web/src/location/chain.ts`) tries **Telegram → WebView → chat pin**, in that locked order. +3. **Acquire a starting point.** The three-link location chain (`web/src/location/chain.ts`) tries **Telegram → WebView → chat pin**, in that locked order. 4. **Route.** The app posts the origin and destination to `/api/route`; the Worker's router (`bot/src/routing/worker-router.ts`) loads the R2-hosted CSR graph once per cold isolate, snaps, and runs A* (`@araharah/routing`). Every miss class answers `200 null` — router-pending, never a wrong line. 5. **Guidance.** Accepting a route mints a guidance envelope (`POST /api/guidance`, 7200 s TTL); a scheduled cron (`*/2 * * * *`) projects progress along the frozen route snapshot and pushes due turn cards — a maneuver glyph photo with a live caption — into the chat, with a button back into the Mini App at `?g=`. @@ -224,16 +224,16 @@ The Worker's `fetch` handler routes exactly six paths and returns `404` for anyt ```bash # Mint a session from a Mini App initData string curl -X POST http://localhost:8787/api/session --data-binary @initdata.txt -# → {"token":""} +# → {"token":""} # Poll the location relay with the token in memory curl -H "Authorization: Bearer " http://localhost:8787/api/location -# → {"pin":null} (honest null, not a fabricated coordinate) +# → {"pin":null} (honest null, not a fabricated coordinate) ``` ### Location acquisition in the Mini App -`web/src/location/chain.ts` is a three-link state machine with a locked order — **Telegram → WebView → chat pin** — and freshness is a separate axis from availability. A Telegram fix byte-identical to the last accepted one routes to the nudge, never to success; denial is a state, not an exception. The chain exposes a `Fix`-shaped abstraction with a pluggable cadence and hard-codes no interval, so continuous-mode polling is a later decision, not a rewrite. Past 45 seconds the strip flips to `SIGNAL LOST` and the last marker dims. +`web/src/location/chain.ts` is a three-link state machine with a locked order — **Telegram → WebView → chat pin** — and freshness is a separate axis from availability. A Telegram fix byte-identical to the last accepted one routes to the nudge, never to success; denial is a state, not an exception. The chain exposes a `Fix`-shaped abstraction with a pluggable cadence and hard-codes no interval, so continuous-mode polling is a later decision, not a rewrite. Past 45 seconds the strip flips to `SIGNAL LOST` and the last marker dims. ### Consuming the design tokens @@ -262,9 +262,9 @@ import ramsStyle from "@araharah/theme/basemap/liberty-rams.json"; The Telemetry Rams design system lives in `theme/` as a Tailwind v4 CSS-first token package — the single source of truth for every color, spacing, typography, and radius value in the project. Consume the tokens by importing `theme/src/tokens.css` (plain CSS custom properties, usable by any stylesheet or the MapLibre basemap) or the compiled stylesheet produced by `npm run build`. The token vocabulary mirrors the mockup screens verbatim, so markup derived from them maps one to one. Rams philosophy lives on in `DESIGN.md`, which is superseded for specifics — values are never restated outside the token package. ```bash -npm run build -w theme # src/theme.css → dist/rams.css (minified) +npm run build -w theme # src/theme.css → dist/rams.css (minified) npm run sheet # build + print the sheet.html path -npm run gallery # build + screenshot → serve gallery.html and basemap on :8123 +npm run gallery # build + screenshot → serve gallery.html and basemap on :8123 npm run audit # off-token audit of the rendered CSS — exits non-zero on violations npm run capture # Playwright screenshots of the token sheet ```