a love letter to tangled (android, iOS, and a search API)
19
fork

Configure Feed

Select the types of activity you want to include in your feed.

1--- 2title: Mobile App Reference 3updated: 2026-03-24 4--- 5 6Twisted 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). 7 8## Tech Stack 9 10- **Vue 3** with TypeScript and Composition API 11- **Ionic Vue** for native-feeling UI components 12- **Capacitor** for iOS/Android builds 13- **Pinia** for state management 14- **TanStack Query** for async data with caching 15- **@atcute/client** and **@atcute/tangled** for AT Protocol XRPC 16 17TypeScript files use `.js` extensions in imports. Package management via pnpm. 18 19## Architecture 20 21Three-layer design: 22 23**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. 24 25**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. 26 27**Data** — Service layer that fetches from external sources and normalizes into domain types. The flow is: Vue component → composable → TanStack Query hook → service function → XRPC call → normalizer → domain model. 28 29## Directory Structure 30 31```sh 32src/ 33 app/ — App shell, router, global config 34 core/ — Shared utilities, constants 35 services/ — API clients and data fetching 36 atproto/ — @atcute client setup, error handling 37 tangled/ — Endpoints, normalizers, TanStack Query hooks 38 domain/ — TypeScript type definitions 39 features/ — Feature modules (home, explore, repo, etc.) 40 components/ — Shared UI components 41``` 42 43## Data Sources 44 45The app reads from multiple sources depending on what's needed: 46 47- **Knots** (Tangled XRPC servers) — Git data: file trees, blobs, commits, branches, diffs. Each repo is hosted on a specific knot. 48- **PDS** (Personal Data Servers) — AT Protocol records: profiles, issues, PRs, comments, stars, follows. Accessed via `com.atproto.repo.getRecord` and `com.atproto.repo.listRecords`. 49- **Twister API** — Search and index-backed summaries (when available). 50- **Constellation** — Social signal counts and backlinks (stars, followers, reactions). 51 52Knots 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. 53 54## Completed Features 55 56### Navigation & Shell (Phase 1) 57 58Five-tab layout with Vue Router, skeleton loaders, placeholder pages. Design system components: RepoCard, UserCard, ActivityCard, FileTreeItem, EmptyState, ErrorBoundary, SkeletonLoader, MarkdownRenderer. 59 60### Public Browsing (Phase 2) 61 62All read-only browsing works without authentication: 63 64**Repository browsing** — Metadata display, README rendering (markdown), file tree navigation, file viewer with syntax context, commit log with pagination, branch listing. 65 66**Profile browsing** — Avatar, bio, links fetched from PDS. User's repos listed. 67 68**Issues** — List view with open/closed state filter, detail view with threaded comments. 69 70**Pull Requests** — List view with status filter (open/closed/merged), detail view with comments. 71 72**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. 73 74## Routing 75 76The app resolves identities through AT Protocol: handle → DID (via PDS resolution) → records. For repo git data, the knot hostname is extracted from the repo's DID document. 77 78Home tab currently provides direct handle-based browsing: enter a known handle to view their profile and repos. This works without any index or search dependency.