A zero-dependency AT Protocol Personal Data Server written in JavaScript
atproto pds
1# pds.js 2 3A zero-dependency AT Protocol Personal Data Server written in JavaScript, running on Cloudflare Workers with Durable Objects. Let's see how far we can get with just Web APIs. 4 5> ⚠️ **Work in progress** - This is experimental. You probably shouldn't use this yet. 6 7## Status 8 9- [x] Repo operations (createRecord, getRecord, putRecord, deleteRecord, applyWrites, listRecords) 10- [x] Sync endpoints (getRepo, getRecord, subscribeRepos, listRepos, getLatestCommit) 11- [x] Auth (createSession, getSession, refreshSession) 12- [x] Handle resolution (resolveHandle) 13- [x] AppView proxy (app.bsky.* forwarding with service auth) 14- [x] Relay notification (requestCrawl) 15- [x] Single or multi-user (each DID gets isolated storage, no self-service signup yet) 16- [x] Blob storage (uploadBlob, getBlob, listBlobs) 17- [x] OAuth 2.0 (PAR, authorization code + PKCE, DPoP-bound tokens, refresh, revoke) 18- [ ] deleteSession (logout) 19- [ ] updateHandle 20- [ ] importRepo 21- [ ] Account management (createAccount, deleteAccount) 22- [ ] Email verification 23- [ ] Invite codes 24- [ ] Admin/moderation 25- [ ] Rate limiting 26 27## Prerequisites 28 29- Node.js 18+ 30 31## Quick Start 32 33```bash 34npm install 35 36# Create local dev config 37cp .env.example .dev.vars 38# Edit .dev.vars with your values 39 40# Run locally 41npm run dev 42``` 43 44## Configuration 45 46For local development, create `.dev.vars`: 47 48``` 49PDS_PASSWORD=your-password # Used for legacy auth and OAuth consent 50JWT_SECRET=your-secret 51RELAY_HOST=https://bsky.network # optional 52``` 53 54For production, use Cloudflare secrets: 55 56```bash 57wrangler secret put PDS_PASSWORD 58wrangler secret put JWT_SECRET 59wrangler secret put RELAY_HOST # optional 60``` 61 62### Blob Storage 63 64Blobs (images, videos) are stored in Cloudflare R2. Create the bucket before deploying: 65 66```bash 67npx wrangler r2 bucket create pds-blobs 68``` 69 70The binding is already configured in `wrangler.toml`. Supported formats: JPEG, PNG, GIF, WebP, MP4. Max size: 50MB. Orphaned blobs are automatically cleaned up after 24 hours. 71 72## Testing 73 74```bash 75npm test # Unit tests 76npm run test:e2e # E2E tests (starts local server) 77``` 78 79## Deploy 80 81```bash 82wrangler deploy 83``` 84 85## Initialize 86 87After deployment, run the setup script to register with PLC and initialize: 88 89```bash 90npm run setup -- --pds https://your-pds.workers.dev 91``` 92 93This generates keys, registers your DID with the PLC directory, initializes the PDS, and saves credentials. Handle defaults to the worker hostname.