Testing implementation for private data in ATProto with ATPKeyserver and ATCute tools
1# ATProto OAuth Application 2 3A full-stack ATProto microblogging application with OAuth authentication. Built with Elysia (backend) and React Router v7 (frontend) in a Bun workspace monorepo. 4 5## Project Structure 6 7``` 8watproto/ 9├── packages/ 10│ ├── server/ # XRPC API server 11│ │ ├── src/ # Server source code 12│ │ ├── data/ # SQLite database 13│ │ └── CLAUDE.md # Server documentation 14│ ├── client/ # React Router v7 frontend (SSR) 15│ │ ├── app/ # React Router app 16│ │ ├── data/ # OAuth state database 17│ │ └── CLAUDE.md # Client documentation 18│ └── lexicon/ # ATProto lexicon types 19│ ├── types/ # Generated types 20│ └── index.ts # Type exports 21├── lexicons/ # Lexicon schemas 22├── package.json # Workspace configuration 23└── CLAUDE.md # Project-wide documentation 24``` 25 26## Tech Stack 27 28**Backend (Server)**: 29- Bun runtime 30- Elysia web framework 31- XRPC protocol (@atcute/xrpc-server) 32- SQLite + Kysely ORM 33 34**Frontend (Client)**: 35- React Router v7 (SSR) 36- ATProto OAuth (@atproto/oauth-client-node) 37- XRPC client (@atcute/client) 38- React 19 39- Tailwind CSS v4 + DaisyUI 40- Vite 41 42**Shared**: 43- @watproto/lexicon - Lexicon type definitions and utils generated from lexicon schemas 44 45## Quick Start 46 47### Prerequisites 48- [Bun](https://bun.sh) v1.0+ 49 50### Installation 51 521. Clone the repository: 53 ```bash 54 git clone <repository-url> 55 cd watproto 56 ``` 57 582. Install dependencies: 59 ```bash 60 bun install 61 ``` 62 633. Create files for environment variables: 64 65 **Server** (`packages/server/.env.local`): 66 ```env 67 PORT=3000 68 DATABASE_URL=./data/dev.db 69 SERVICE_DID=did:web:localhost:3000 70 ``` 71 72 **Client** (`packages/client/.env.local`): 73 ```env 74 CLIENT_URL=http://your.client.host 75 API_URL=http://localhost:3000 76 DEFAULT_PDS_URL=https://your.pds.host 77 DB_PATH=./data/state.db 78 PORT=5173 79 AUTH_SECRET=your-random-secret-key-here 80 KEYSERVER_DID=did:web:your.keyserver.host 81 ``` 82 83 Generate `AUTH_SECRET` with: `openssl rand -base64 32` 84 85 To use OAuth in `localhost` do not define a `CLIENT_URL` here 86 87 More on environment variables [below](#environment-variables) 88 89### Development 90 91Run both server and client in separate terminals: 92 93**Terminal 1 - Server**: 94```bash 95cd packages/server 96bun run dev 97``` 98 99**Terminal 2 - Client**: 100```bash 101cd packages/client 102bun run dev 103``` 104 105Then you can open: 106- **Frontend**: http://127.0.0.1:5173 107- **XRPC Server**: http://localhost:3000 108 109### Alternative: Run from Root 110 111You can also use workspace scripts from the root: 112 113```bash 114# Start server only 115bun run dev 116 117# Start client only 118bun run dev:client 119 120# Build both packages 121bun run build 122 123# Type check all packages 124bun run typecheck 125``` 126 127This has the advantage of being slightly easier to run, but logs will be slightly more cluttered. 128 129## Project Commands 130 131### Root Commands 132```bash 133bun install # Install all workspace dependencies 134bun run dev # Start both server and client 135bun run dev:server # Start server only 136bun run dev:client # Start client only 137bun run build # Build client for production 138bun run typecheck # Type check all packages 139bun run lex # Generate TypeScript types from lexicon schemas 140``` 141 142### Server Commands (packages/server) 143```bash 144bun run dev # Start development server (port 3000) 145bun run start # Start production server 146bun run debug # Start with debugger 147bun run db:codegen # Regenerate database types 148bun run db:migrate # Run database migrations 149bun run typecheck # Type check 150``` 151 152### Client Commands (packages/client) 153```bash 154bun run dev # Start development server (port 5173) 155bun run build # Build for production 156bun run start # Start production server 157bun run lint # Run ESLint 158bun run typecheck # Type check 159``` 160 161## Features 162 163### Current 164- ✅ ATProto OAuth authentication (client-side SSR) 165- ✅ Session management with SQLite 166- ✅ XRPC server and client communication 167- ✅ Post creation and storage (public and private) 168- ✅ Tag system for posts 169- ✅ User authentication UI (login flow) 170- ✅ Basic UI components (Header, PostFeed, UserMenu) 171- ✅ Lexicon type generation 172- ✅ React Router v7 frontend with SSR 173- ✅ Tailwind CSS + DaisyUI styling 174- ✅ TypeScript throughout 175 176### Planned 177- 🚧 ATProto feed aggregation and timeline 178- 🚧 User profile pages 179- 🚧 Media upload (images/videos) 180- 🚧 Real-time updates via WebSockets 181- 🚧 Background job processing 182- 🚧 Full-text search 183- 🚧 Multi-account support 184 185## Architecture 186 187### Backend (packages/server) 188- **Framework**: Elysia (fast, type-safe web framework) 189- **Protocol**: XRPC (ATProto RPC protocol) 190- **Database**: SQLite with Kysely query builder 191- **Features**: Post storage, account management, ID resolution 192 193### Frontend (packages/client) 194- **Framework**: React Router v7 (with SSR) 195- **OAuth**: ATProto OAuth Client (server-side) 196- **Database**: SQLite for OAuth state 197- **Routing**: File-based routes in `app/routes/` 198- **Styling**: Tailwind CSS v4 + DaisyUI 199- **Build**: Vite 200 201### Shared (packages/lexicon) 202- **Purpose**: ATProto lexicon type definitions 203- **Generator**: @atcute/lex-cli 204- **Usage**: Shared types across server and client 205 206### Communication 207- Client ↔ Server: XRPC protocol over HTTP 208- Authentication: OAuth managed by client SSR 209- Session: SQLite database with httpOnly cookies 210 211## Deployment 212 213### Server 214Deploy to Node/Bun compatible hosting: 215- [Fly.io](https://fly.io) 216- [Railway](https://railway.app) 217- [Render](https://render.com) 218 219### Client 220Deploy to static hosting: 221- [Vercel](https://vercel.com) 222- [Netlify](https://netlify.com) 223- [Cloudflare Pages](https://pages.cloudflare.com) 224 225### Environment Variables 226Configure production environment variables in your hosting provider: 227 228**Server**: 229- `PORT` - Server port (default: 3000) 230- `DATABASE_URL` - SQLite database path 231- `SERVICE_DID` - DID that points to this service (required) 232 233**Client**: 234- `API_URL` - XRPC server URL (required) 235- `DEFAULT_PDS_URL` - Default PDS URL for OAuth (required) 236- `AUTH_SECRET` - Session encryption secret (required) 237- `KEYSERVER_DID` - DID that poins to a [Keyserver](https://tangled.org/@djara.dev/atp-keyserver) for encryption / decryption (required) 238- Optional: `CLIENT_URL`, `DB_PATH`, `PORT` 239 240**Important**: Client requires SSR-capable hosting with writable filesystem for OAuth database 241 242## Documentation 243 244Detailed documentation is available in CLAUDE.md files: 245- **Root**: `CLAUDE.md` - Monorepo overview and workflow 246- **Server**: `packages/server/CLAUDE.md` - Backend architecture and patterns 247- **Client**: `packages/client/CLAUDE.md` - Frontend architecture and patterns 248 249## Development Workflow 250 251### Adding a Backend Feature 2521. Navigate to `packages/server` 2532. Create/modify XRPC procedures in `src/` 2543. Add database migrations if needed 2554. Test with `bun run dev` 2565. See `packages/server/CLAUDE.md` for patterns 257 258### Adding a Frontend Feature 2591. Navigate to `packages/client` 2602. Create route file in `app/routes/` 2613. Create components as needed 2624. Style with Tailwind CSS + DaisyUI 2635. Test with `bun run dev` 2646. See `packages/client/CLAUDE.md` for patterns 265 266### Working with Lexicons 267```bash 268# Add or modify lexicon schemas in lexicons/ directory 269# Then regenerate TypeScript types: 270bun run lex 271 272# Types are generated in packages/lexicon/types/ 273# Available via: import { Watproto } from '@watproto/lexicon' 274``` 275 276### Database Migrations 277```bash 278cd packages/server 279 280# Create migration file manually in src/db/migrations/ 281# Then regenerate types: 282bun run db:codegen 283``` 284 285## Troubleshooting 286 287**Port already in use**: 288- Change `PORT` in `packages/server/.env.local` 289- Client will auto-increment port if 5173 is taken 290 291**CORS errors**: 292- Ensure server CORS allows client origin 293- Check `API_URL` in client environment variables matches server URL 294 295**Type errors**: 296- Run `bun install` at root to sync workspace 297- Run `bun run typecheck` to find issues 298 299**Database issues**: 300- Delete `packages/server/data/*.db*` files 301- Restart server to recreate database 302 303## License 304 305MIT 306 307## Contributing 308 309See CLAUDE.md for development guidelines and architecture patterns.