This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
OpenPDS is a directory of AT Protocol PDS servers with open registration. It runs on Val Town as a serverless app with two entry points: an HTTP server and a daily cron job. Data comes from mary-ext/atproto-scraping and gets enriched with health, geo-IP, version, and trust metadata.
deno task check # Type check entry points deno task test # Run tests (--allow-net --allow-read --allow-import) deno fmt # Format all files deno lint # Lint all .ts files deno task deploy # fmt + lint + check + test + vt push (full deploy pipeline)
Do not use vt push directly — always use deno task deploy which runs
quality checks first.
Runtime: Deno on Val Town. Framework: Hono. Database: Val Town
SQLite. Imports: via esm.sh (not npm/node_modules).
backend/index.http.ts — HTTP trigger. Hono app serving HTML directory (/)
and JSON API (/api/servers). Runs migrations on first request.cron/refresh.cron.ts — Cron trigger. Daily refresh: fetch PDS list → sync to
DB → fetch latest version → enrich batch of servers.pds-fetcher.ts downloads state.json (~2900 PDSes)version-checker.ts gets latest PDS version from GitHub APIpds-enricher.ts enriches a batch (configurable, default 20): DNS resolve →
health check → describeServer → listRepos user count → geo-IP batch lookupupdateEnrichment()backend/database/ — migrations.ts (schema), queries.ts (all SQL
operations, row-to-object mapping)backend/routes/ — pages.ts (server-rendered HTML), api.ts (JSON
endpoint)backend/services/ — Pure async functions: pds-fetcher, pds-enricher,
geo-resolver, version-checkershared/ — types.ts (all TypeScript interfaces), constants.ts (config
values, country flag helper)cron/ — Scheduled job orchestration5 boolean signals, each worth 20%: contact email, ToS, privacy policy, active users (>5), latest PDS version. Calculated in SQL via CASE expressions.
app.fetch, cron files
export a default async functionhttps://esm.town/v/stevekrouse/sqlite_2, _3) rather than ALTER
TABLEDeno namespace in shared/ code (must work in browser context too)Deno.env.get(), never hardcodedsnake_case. TypeScript code: camelCase. rowToServer()
maps between them.AbortSignal.timeout() (5s for PDS endpoints, 10s
for geo batch)Promise.allSettled() for partial-failure resilienceesc() function for XSS prevention