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.

Go 35.0%
Vue 27.5%
TypeScript 24.0%
HTML 2.9%
Shell 1.9%
CSS 1.6%
JavaScript 1.4%
Swift 1.0%
Batchfile 0.6%
Just 0.3%
Java 0.3%
Dockerfile 0.1%
Other 3.3%
28 1 2

Clone this repository

https://tangled.org/desertthunder.dev/twisted https://tangled.org/did:plc:xg2vq45muivyy3xwatcehspu/twisted
git@tangled.org:desertthunder.dev/twisted git@tangled.org:did:plc:xg2vq45muivyy3xwatcehspu/twisted

For self-hosted knots, clone URLs may differ based on your setup.

Download tar.gz
README.md

Twisted#

Twisted is a monorepo for a Tangled mobile client and the supporting Tap-backed indexing API.

Projects#

  • apps/twisted: Ionic Vue client for browsing Tangled repos, profiles, issues, PRs, and indexed search results
  • packages/api: Go service that consumes Tangled records through Tap, fills gaps in the public Tangled API, and serves search
  • docs: top-level specs and plans, split by project under docs/app and docs/api

Architecture#

The app still uses Tangled's public knot and PDS APIs for canonical repo and profile data. The API project adds two complementary capabilities:

  1. Global search over indexed Tangled content
  2. Index-backed summaries for data that is hard to derive from the public API alone, such as followers

That keeps direct browsing honest while giving the client one place to ask for cross-network discovery and graph augmentation.

Development#

Use the top-level justfile for common workflows:

just dev
just build
just test
just api-run-api

To enable indexed search in the client, set VITE_TWISTER_API_BASE_URL in apps/twisted/.env.

Run Locally#

Install dependencies once from the repo root:

pnpm install

Start the Ionic/Vite app:

pnpm dev
# or: just dev

That serves the client from apps/twisted with Vite.

To run the Go API locally, make sure packages/api/.env has at least:

  • TURSO_DATABASE_URL
  • TURSO_AUTH_TOKEN

Then start the API:

pnpm api:run:api
# or: just api-dev

This serves the API and search site on http://localhost:8080.

To run the indexer as well, packages/api/.env also needs:

  • TAP_URL
  • TAP_AUTH_PASSWORD
  • INDEXED_COLLECTIONS

Then start the indexer in a separate terminal:

pnpm api:run:indexer
# or: just api-run-indexer

Typical local setup is three terminals:

  1. pnpm dev
  2. pnpm api:run:api
  3. pnpm api:run:indexer

If you want the app to call the local API, set this in apps/twisted/.env:

VITE_TWISTER_API_BASE_URL=http://localhost:8080

Infrastructure Setup#

Turso#

Use one Turso database per environment, for example:

  • twister-dev
  • twister-prod

Do not introduce separate app variable names for dev and prod. Always use the same variables:

  • TURSO_DATABASE_URL
  • TURSO_AUTH_TOKEN

Only the values change per environment.

Example:

# Development
TURSO_DATABASE_URL=libsql://twister-dev-your-org.turso.io
TURSO_AUTH_TOKEN=...

# Production
TURSO_DATABASE_URL=libsql://twister-prod-your-org.turso.io
TURSO_AUTH_TOKEN=...

Railway#

Create or reuse one Railway project containing:

  • existing tap
  • api running twister api
  • indexer running twister indexer

Set these shared variables on the Railway services:

  • TURSO_DATABASE_URL
  • TURSO_AUTH_TOKEN
  • LOG_LEVEL
  • LOG_FORMAT

Set these API-specific variables:

  • HTTP_BIND_ADDR
  • SEARCH_DEFAULT_LIMIT
  • SEARCH_MAX_LIMIT

Set these indexer-specific variables:

  • TAP_URL
  • TAP_AUTH_PASSWORD
  • INDEXED_COLLECTIONS

If you use separate Railway environments for dev and prod, keep the same variable names in both and only swap the Turso values.

First Bootstrap#

For a brand-new environment:

  1. Point TURSO_DATABASE_URL and TURSO_AUTH_TOKEN at the target database.
  2. Deploy api and indexer on Railway.
  3. Verify API readiness and indexer health.
  4. Run twister backfill with your seed file.
  5. Treat the environment as search-ready only after historical backfill completes.

Docs#