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
27See [endpoint comparison](docs/endpoint-comparison.md) for detailed coverage vs the official atproto PDS.
28
29## Prerequisites
30
31- Node.js 18+
32
33## Quick Start
34
35```bash
36npm install
37
38# Create local dev config
39cp .env.example .dev.vars
40# Edit .dev.vars with your values
41
42# Run locally
43npm run dev
44```
45
46## Configuration
47
48For local development, create `.dev.vars`:
49
50```
51PDS_PASSWORD=your-password # Used for legacy auth and OAuth consent
52JWT_SECRET=your-secret
53RELAY_HOST=https://bsky.network # optional
54```
55
56For production, use Cloudflare secrets:
57
58```bash
59wrangler secret put PDS_PASSWORD
60wrangler secret put JWT_SECRET
61wrangler secret put RELAY_HOST # optional
62```
63
64### Blob Storage
65
66Blobs (images, videos) are stored in Cloudflare R2. Create the bucket before deploying:
67
68```bash
69npx wrangler r2 bucket create pds-blobs
70```
71
72The 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.
73
74## Testing
75
76```bash
77npm test # Unit tests
78npm run test:e2e # E2E tests (starts local server)
79```
80
81## Deploy
82
83```bash
84wrangler deploy
85```
86
87## Initialize
88
89After deployment, run the setup script to register with PLC and initialize:
90
91```bash
92npm run setup -- --pds https://your-pds.workers.dev
93```
94
95This generates keys, registers your DID with the PLC directory, initializes the PDS, and saves credentials. Handle defaults to the worker hostname.