sveltekit + contrail + atproto OAuth#
A sveltekit example app on cloudflare workers with self-hosted atproto record indexing via contrail, fully typed queries, and OAuth authentication.
Setup#
pnpm install
pnpm dev
Dev mode uses a loopback OAuth client — no keys or Cloudflare setup needed.
Config#
Define which AT Protocol collections to index in src/lib/contrail.config.ts:
import type { ContrailConfig } from '@atmo-dev/contrail';
export const config: ContrailConfig = {
namespace: 'statusphere.app',
collections: {
status: { // short name → URL path segment
collection: 'xyz.statusphere.status', // full NSID of the record type
queryable: {
status: {}, // equality filter (?status=...)
createdAt: { type: 'range' } // range filter (?createdAtMin=...&createdAtMax=...)
}
}
}
};
After changing the config, run pnpm generate:pull to regenerate lexicons and types.
Run pnpm sync to backfill existing records from the network.
Wrangler bindings (wrangler.jsonc):
- D1 (
DB) — contrail's database - KV (
OAUTH_SESSIONS,OAUTH_STATES) — OAuth session storage - Vars —
CRON_SECRET,OAUTH_PUBLIC_URL,CLIENT_ASSERTION_KEY,COOKIE_SECRET
Deploy#
npx wrangler d1 create statusphere
# Add database_id to wrangler.jsonc
pnpm build
npx wrangler deploy
How it works#
Contrail indexes AT Protocol records into D1 via Jetstream (cron, every minute). When a user posts, contrail.notify() indexes it immediately.
Typed queries use @atcute/client with an in-process handler — full type safety, zero HTTP overhead:
const client = getClient(platform!.env.DB);
const res = await client.get('statusphere.app.status.listRecords', {
params: { limit: 50, profiles: true } // typed params
});
res.data.records // typed response
Types are generated from contrail's config via pnpm generate:pull, which produces lexicon JSON and TypeScript types that register with @atcute/client.
Scheduled ingestion works around SvelteKit's lack of scheduled export support (sveltejs/kit#4841) by appending a handler post-build that self-calls /api/cron.
OAuth uses @atcute/oauth-node-client with KV-backed sessions and HMAC-signed cookies.
License#
MIT