See the best posts from any Bluesky account
0
fork

Configure Feed

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

add AGENTS.md

+81
+80
AGENTS.md
··· 1 + # CLAUDE.md 2 + 3 + This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. 4 + 5 + ## Project 6 + 7 + skystar.social — a favstar.fm-style Bluesky web app. Given a handle, shows that user's top-25 most-liked or most-reposted posts (all-time / last month). Live engagement comes from the Bluesky Jetstream firehose; first-lookup backfill hits the AppView API. 8 + 9 + ## Stack 10 + 11 + - **TypeScript + AdonisJS v7** (web + workers, single repo, no monorepo — `apps/web` was flattened to root in commit c46cdbb) 12 + - **ClickHouse** — append-only store for engagement events + post snapshots 13 + - **SQLite** (via Lucid) — metadata: tracked users, jetstream cursor, backfill jobs 14 + - **Node 24**, **pnpm 10** (pinned in `mise.toml`; the repo migrated from npm in c46cdbb) 15 + - **Edge.js** templates, **Alpine.js** + **Vite** on the frontend 16 + - Ships as one Docker image with three process entrypoints. 17 + 18 + ## Commands 19 + 20 + Preferred workflow is via `mise` tasks (see `mise.toml`): 21 + 22 + ```bash 23 + mise run dev # ClickHouse + migrations + web + jetstream + queue (parallel) 24 + mise run db:wait # Start ClickHouse, wait for /ping 25 + mise run db:migrate # Run Lucid + ClickHouse migrations 26 + mise run dev:web # node ace serve --hmr 27 + mise run dev:jetstream # node ace jetstream:consume 28 + mise run dev:queue # node ace queue:work 29 + ``` 30 + 31 + Direct pnpm scripts: 32 + 33 + ```bash 34 + pnpm dev # node ace serve --hmr 35 + pnpm test # node ace test (Japa) 36 + pnpm lint # eslint . 37 + pnpm typecheck # tsc --noEmit 38 + pnpm build # node ace build 39 + ``` 40 + 41 + Running a single test: `node ace test --files "tests/unit/clickhouse_store.spec.ts"` (Japa file filter). The Japa runner is configured in `adonisrc.ts`. 42 + 43 + Ace commands live in `commands/` — notably `node ace clickhouse:migrate` (applies SQL files in `database/clickhouse/`) and `node ace jetstream:consume`. 44 + 45 + ## Architecture 46 + 47 + Three process entrypoints, one codebase: 48 + 49 + 1. **HTTP web server** (`bin/server.ts`) — controllers in `app/controllers/`, routes in `start/routes.ts`. Profile pages (`/profile/:handle/likes|reposts`) are the main product surface. Health checks at `/health/live` (public) and `/health/ready` (gated by `HEALTH_CHECK_TOKEN` via `x-monitoring-secret` header). 50 + 2. **Jetstream consumer** (`node ace jetstream:consume`) — `app/services/jetstream_consumer.ts` connects to the Bluesky Jetstream WebSocket, filters for tracked DIDs, writes engagement events to ClickHouse, and persists cursor position to SQLite via `jetstream_cursor_io.ts`. The consumer takes a `WebSocketLike` factory so tests can inject fakes. 51 + 3. **Queue worker** (`node ace queue:work`, `@adonisjs/queue`) — runs `app/jobs/backfill_job.ts` which fetches historical posts/likes/reposts from the AppView on first lookup of a new handle. 52 + 53 + ### Data flow 54 + 55 + - Handle → `HandleResolver` (SQLite lookup or AppView resolution) → persisted to `users` table (DID is the tracked identity) 56 + - First time we see a DID: enqueue a backfill job; Jetstream consumer also starts tracking it for live events 57 + - Queries for top-N posts read from ClickHouse (`app/lib/clickhouse/store.ts`) joining engagement events with post snapshots 58 + - Cursor checkpoint so Jetstream resumes after restart 59 + 60 + ### Key modules 61 + 62 + - `app/lib/atproto/` — AppView client + Jetstream event parsers. Import via `#lib/atproto/index` (path alias). Previously lived in `packages/atproto`, flattened in commit 0cea00e. 63 + - `app/lib/clickhouse/` — ClickHouse client wrapper + query store. Import via `#lib/clickhouse/index`. **Tests must drain query streams** — see commit c46cdbb; undrained streams hang the test process. 64 + - `database/schema.ts` + `database/schema_rules.ts` — Lucid schema definitions; `database/migrations/` for SQLite; `database/clickhouse/*.sql` for ClickHouse DDL (numbered, applied in order). 65 + - `config/` — standard AdonisJS config (app, database, queue, session, shield, static, vite). `start/env.ts` defines required env vars via Vine schema. 66 + 67 + ### Path aliases 68 + 69 + Defined in `package.json` `imports` — use `#controllers/*`, `#services/*`, `#models/*`, `#lib/*`, `#jobs/*`, `#database/*`, `#tests/*`, `#start/*`, `#config/*`. These map to the `.js` extension even in TS source (AdonisJS convention). 70 + 71 + ## Edge templates gotcha 72 + 73 + Edge uses `{{ handle }}` for interpolation, **not** `{{{ handle }}}`. There was a recent bug (ac30713) where `@{{ handle }}` rendered as literal `@<handle>` because of Edge's `@` tag parsing — if you're rendering a handle preceded by `@`, escape the `@` or use `{{ '@' + handle }}`. 74 + 75 + ## Testing notes 76 + 77 + - Japa runner (`@japa/runner`), configured in `adonisrc.ts`. 78 + - Tests split into `tests/unit/` and `tests/functional/`. 79 + - ClickHouse tests use real ClickHouse (docker compose). Never mock it — always drain query result streams to avoid hangs. 80 + - Fixtures live next to specs (e.g. `clickhouse_store_fixtures.ts`).
+1
CLAUDE.md
··· 1 + AGENTS.md
tmp/.gitkeep

This is a binary file and will not be displayed.