···2828just api-run-api
2929```
30303131-To enable indexed search in the client, set `VITE_TWISTER_API_BASE_URL` in `apps/twisted/.env`.
3131+The committed `apps/twisted/.env` points at production. Use `apps/twisted/.env.local`
3232+for machine-local overrides such as a localhost API or OAuth callback.
32333334## Run Locally
3435···94952. `pnpm api:run:api`
95963. `pnpm api:run:indexer`
96979797-If you want the app to call the local API, set this in `apps/twisted/.env`:
9898+If you want the app to call the local API, put this in `apps/twisted/.env.local`:
989999100```bash
100101VITE_TWISTER_API_BASE_URL=http://localhost:8080
101102```
103103+104104+Dev builds keep the current OAuth flow available. Production builds are read-only
105105+and hide auth entry points for now.
102106103107### Local API DB
104108
+5-4
apps/twisted/.env.example
···11-VITE_TWISTER_API_BASE_URL=http://127.0.0.1:8080
11+VITE_TWISTER_API_BASE_URL=https://twister.stormlightlabs.org
2233# OAuth configuration
44-# VITE_OAUTH_CLIENT_ID must be a publicly accessible URL (use a tunnel for local dev)
55-# VITE_OAUTH_CLIENT_ID=https://your-tunnel.example.com/oauth/client-metadata.json
66-VITE_OAUTH_REDIRECT_URI=http://127.0.0.1:5173/oauth-callback
44+# Auth is currently exposed in dev builds only. Override these in .env.local
55+# if you need local OAuth testing against localhost.
66+VITE_OAUTH_CLIENT_ID=https://twister.stormlightlabs.org/oauth/client-metadata.json
77+VITE_OAUTH_REDIRECT_URI=https://twister.stormlightlabs.org/oauth-callback
+18-6
apps/twisted/README.md
···6677- Node.js 20+
88- pnpm
99-- The Twister API running locally
99+- The Twister API running locally if you want local API overrides
10101111## Running locally
1212···1414# From the repo root, install dependencies
1515pnpm install
16161717-# Copy env file and point it at your local Twister API
1818-cp apps/twisted/.env.example apps/twisted/.env
1717+# Local overrides live in .env.local
1818+cp apps/twisted/.env.example apps/twisted/.env.local
19192020# Start the Vite dev server
2121cd apps/twisted
···26262727## Environment variables
28282929-| Variable | Default | Description |
3030-| --------------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------- |
3131-| `VITE_TWISTER_API_BASE_URL` | `http://localhost:8080` | Base URL of the Twister API. All app requests (AT Protocol, Jetstream, Constellation) are proxied through this. |
2929+Committed `.env` defaults point at production:
3030+3131+- `VITE_TWISTER_API_BASE_URL=https://twister.stormlightlabs.org`
3232+- `VITE_OAUTH_CLIENT_ID=https://twister.stormlightlabs.org/oauth/client-metadata.json`
3333+- `VITE_OAUTH_REDIRECT_URI=https://twister.stormlightlabs.org/oauth-callback`
3434+3535+Use `.env.local` for local overrides:
3636+3737+| Variable | Local example | Description |
3838+| --------------------------- | -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
3939+| `VITE_TWISTER_API_BASE_URL` | `http://localhost:8080` | Base URL of the Twister API. All app requests (AT Protocol, Jetstream, Constellation) are proxied through this. |
4040+| `VITE_OAUTH_CLIENT_ID` | `http://127.0.0.1:8080/oauth/client-metadata.json` | Public OAuth metadata URL for local dev auth flows. |
4141+| `VITE_OAUTH_REDIRECT_URI` | `http://127.0.0.1:5173/oauth-callback` | Redirect URI used by the local Vite app during OAuth testing. |
4242+4343+Production builds hide auth entry points for now. Dev builds keep OAuth enabled.
32443345> All upstream requests — knot XRPC, PDS records, handle resolution, DID documents,
3446> Constellation backlink counts, and the Jetstream activity stream — are routed
···11---
22title: Mobile App Reference
33-updated: 2026-03-24
33+updated: 2026-03-25
44---
5566Twisted is an Ionic Vue mobile app for browsing Tangled, a git hosting platform built on the AT Protocol. It targets iOS and Android via Capacitor (no web target).
···20202121Three-layer design:
22222323-**Presentation** — Vue components and pages using Ionic's component library. Five-tab navigation: Home, Explore, Activity, Profile (visible tabs) plus Repo (pushed route). Repo detail uses segmented tabs: Overview, Files, Issues, PRs.
2323+**Presentation** — Vue components and pages using Ionic's component library. Five-tab navigation: Home, Explore, Activity, Bookmarks/Profile, Settings. Repo detail uses segmented tabs: Overview, Files, Issues, PRs.
24242525**Domain** — TypeScript types modeling the app's data: UserSummary, RepoSummary, RepoDetail, RepoFile, PullRequestSummary, IssueSummary, ActivityItem. These are app-internal representations, decoupled from API response shapes.
2626···4949- **Twister API** — Search and index-backed summaries (when available).
5050- **Constellation** — Social signal counts and backlinks (stars, followers, reactions).
51515252-Knots serve XRPC endpoints for git operations. The appview at `tangled.org` returns HTML only (no JSON API), so the app goes directly to knots for git data and PDS for AT Protocol records.
5252+The app calls the Twister API for app data. Twister proxies knot and PDS reads,
5353+handle resolution, Constellation counts, and the Jetstream activity stream.
53545455## Completed Features
55565657### Navigation & Shell (Phase 1)
57585858-Five-tab layout with Vue Router, skeleton loaders, placeholder pages. Design system components: RepoCard, UserCard, ActivityCard, FileTreeItem, EmptyState, ErrorBoundary, SkeletonLoader, MarkdownRenderer.
5959+Five-tab layout with Vue Router, skeleton loaders, placeholder pages, and a
6060+local Bookmarks area for repos, strings, and saved files.
59616062### Public Browsing (Phase 2)
61636262-All read-only browsing works without authentication:
6464+All release-mode browsing works without authentication:
63656466**Repository browsing** — Metadata display, README rendering (markdown), file tree navigation, file viewer with syntax context, commit log with pagination, branch listing.
6567···69717072**Pull Requests** — List view with status filter (open/closed/merged), detail view with comments.
71737272-**Caching** — TanStack Query configured with per-data-type stale times. Persistence via Dexie (IndexedDB) — works in Capacitor's WebView on device and in the browser during local dev.
7474+**Caching** — TanStack Query configured with per-data-type stale times.
7575+Persistence currently uses IndexedDB via `idb-keyval`, with a separate local
7676+bookmarks store for saved repos, strings, files, and READMEs.
7777+7878+## Storage Migration
7979+8080+IndexedDB is the current implementation for cache and bookmark persistence, but
8181+it should be treated as an interim step.
8282+8383+- Local cache and offline-content storage should migrate toward SQLite so larger
8484+ saved payloads, better inspection, and more explicit schema management are
8585+ available on-device.
8686+- Sensitive auth/session material should migrate toward Ionic secure storage
8787+ instead of living in browser-style storage primitives.
8888+- Until that migration lands, IndexedDB should stay limited to non-sensitive
8989+ cached data and user-saved offline reading content.
9090+9191+## Auth Split
9292+9393+Production builds are read-only and hide auth entry points. Dev builds keep the
9494+current OAuth flow available for testing future authenticated features.
73957496## Routing
7597
+4-3
docs/roadmap.md
···102102103103**Depends on:** App: Search & Discovery (for cache persistence of search/feed data)
104104105105-- [ ] Dexie setup with database schema (query cache + pinned content tables)
106106-- [ ] TanStack Query persister backed by Dexie
105105+- [x] IndexedDB-backed local cache and bookmark storage for first release
106106+- [ ] Migrate offline cache and saved-content storage from IndexedDB to SQLite
107107+- [ ] TanStack Query persister backed by SQLite or equivalent app-managed store
107108- [ ] Pinned content store (save/unsave files for offline reading)
108109- [ ] Pinned files UI (list, pin/unpin actions on file viewer, last-fetched timestamp)
109110- [ ] Offline detection and banner
110110-- [ ] Secure token storage (Capacitor Secure Storage)
111111+- [ ] Migrate auth/session data to Ionic secure storage
111112- [ ] Cache eviction (per-type limits and TTL, pinned content exempt)
112113- [ ] List virtualization for large datasets
113114- [ ] Lazy-load avatars, prefetch on hover