···11+# Getting Started
22+33+## Prerequisites
44+55+- [Node.js](https://nodejs.org/) v18+
66+- [pnpm](https://pnpm.io/)
77+- A [Cloudflare account](https://dash.cloudflare.com/sign-up) (for production)
88+99+## Local Development
1010+1111+```sh
1212+pnpm install
1313+pnpm dev
1414+```
1515+1616+That's it. In dev mode the app uses a loopback OAuth client — no keys, no Cloudflare setup, no secrets. It binds to `127.0.0.1:5183` (required for AT Protocol loopback OAuth).
1717+1818+Open http://127.0.0.1:5183 and log in with any Bluesky handle.
1919+2020+## Configure your app
2121+2222+Edit `src/lib/atproto/settings.ts` to set the collections your app reads/writes:
2323+2424+```ts
2525+export const permissions = {
2626+ collections: ['xyz.statusphere.status'],
2727+ rpc: {},
2828+ blobs: []
2929+} as const;
3030+```
3131+3232+The OAuth scope is auto-generated from this config.
3333+3434+## Deploy to Production
3535+3636+### 1. Create KV namespaces
3737+3838+```sh
3939+npx wrangler kv namespace create OAUTH_SESSIONS
4040+npx wrangler kv namespace create OAUTH_STATES
4141+```
4242+4343+Each command outputs an ID. Put them in `wrangler.jsonc`:
4444+4545+```jsonc
4646+"kv_namespaces": [
4747+ { "binding": "OAUTH_SESSIONS", "id": "<your-id>" },
4848+ { "binding": "OAUTH_STATES", "id": "<your-id>" }
4949+]
5050+```
5151+5252+### 2. Set your public URL
5353+5454+In `wrangler.jsonc`, set `OAUTH_PUBLIC_URL` to your production domain:
5555+5656+```jsonc
5757+"vars": {
5858+ "OAUTH_PUBLIC_URL": "https://your-domain.com"
5959+}
6060+```
6161+6262+### 3. Generate and set secrets
6363+6464+```sh
6565+pnpm env:generate-key
6666+npx wrangler secret put CLIENT_ASSERTION_KEY # paste the output
6767+6868+pnpm env:generate-secret
6969+npx wrangler secret put COOKIE_SECRET # paste the output
7070+```
7171+7272+### 4. Deploy
7373+7474+```sh
7575+npx wrangler deploy
7676+```
7777+7878+Then add a custom domain in the Cloudflare dashboard (Worker > Settings > Domains & Routes).
7979+8080+## Dev with tunnel (optional)
8181+8282+To test the full confidential client flow locally using [cloudflared](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/):
8383+8484+```sh
8585+pnpm env:setup-dev # generates secrets in .env
8686+cloudflared tunnel --url http://localhost:5183 # start tunnel (note the URL it prints)
8787+```
8888+8989+Add the tunnel URL to `.env`:
9090+9191+```
9292+OAUTH_PUBLIC_URL=https://your-tunnel-id.trycloudflare.com
9393+```
9494+9595+Then `pnpm dev`. The app will use a confidential client with that URL.
9696+9797+## Scripts
9898+9999+| Script | Description |
100100+|---|---|
101101+| `pnpm dev` | Start dev server |
102102+| `pnpm build` | Build for production |
103103+| `pnpm check` | Run svelte-check |
104104+| `pnpm env:generate-key` | Generate client assertion key |
105105+| `pnpm env:generate-secret` | Generate cookie signing secret |
106106+| `pnpm env:setup-dev` | Generate both secrets and write to `.env` |
107107+108108+## Optional: Profile caching
109109+110110+Create a KV namespace for caching Bluesky profiles (1 hour TTL):
111111+112112+```sh
113113+npx wrangler kv namespace create PROFILE_CACHE
114114+```
115115+116116+Add it to `wrangler.jsonc` alongside the other namespaces:
117117+118118+```jsonc
119119+{ "binding": "PROFILE_CACHE", "id": "<your-id>" }
120120+```
121121+122122+Without this, profiles are fetched fresh on every page load. The app works fine either way.
···99pnpm dev
1010```
11111212-In dev mode the app uses a **loopback OAuth client** (no keys, in-memory storage). It binds to `127.0.0.1:5183` — required for AT Protocol loopback OAuth.
1313-1414-### Dev with tunnel (confidential client)
1515-1616-To test the full production flow locally with a tunnel like [cloudflared](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/):
1717-1818-```sh
1919-pnpm env:setup-dev # generates secrets in .env
2020-# add OAUTH_PUBLIC_URL=https://your-tunnel.trycloudflare.com to .env
2121-cloudflared tunnel --url http://localhost:5183 # start tunnel
2222-pnpm dev # start dev server
2323-```
2424-2525-## Production Deployment
2626-2727-### 1. Create KV namespaces
2828-2929-```sh
3030-npx wrangler kv namespace create OAUTH_SESSIONS
3131-npx wrangler kv namespace create OAUTH_STATES
3232-```
3333-3434-Add the IDs to `wrangler.jsonc`:
3535-3636-```jsonc
3737-"kv_namespaces": [
3838- { "binding": "OAUTH_SESSIONS", "id": "<your-id>" },
3939- { "binding": "OAUTH_STATES", "id": "<your-id>" }
4040-]
4141-```
4242-4343-### 2. Set your public URL
4444-4545-In `wrangler.jsonc`:
4646-4747-```jsonc
4848-"vars": {
4949- "OAUTH_PUBLIC_URL": "https://your-domain.com"
5050-}
5151-```
5252-5353-### 3. Generate and set secrets
5454-5555-```sh
5656-pnpm env:generate-key
5757-npx wrangler secret put CLIENT_ASSERTION_KEY # paste generated key
5858-5959-pnpm env:generate-secret
6060-npx wrangler secret put COOKIE_SECRET # paste generated secret
6161-```
6262-6363-### 4. Configure permissions
6464-6565-Edit `src/lib/atproto/settings.ts`:
1212+Dev mode uses a loopback OAuth client — no keys or Cloudflare setup needed. Open http://127.0.0.1:5183 and log in with any Bluesky handle.
66136767-```ts
6868-export const permissions = {
6969- collections: ['xyz.statusphere.status'], // collections your app can read/write
7070- rpc: {}, // authenticated RPC requests
7171- blobs: [] // blob types your app can upload
7272-} as const;
7373-```
7474-7575-The OAuth scope is auto-generated from this config.
7676-7777-### 5. Deploy
7878-7979-```sh
8080-npx wrangler deploy
8181-```
8282-8383-Set up a custom domain in the Cloudflare dashboard (Worker > Settings > Domains & Routes) so the OAuth client metadata URL matches your `client_id`.
8484-8585-## Scripts
8686-8787-| Script | Description |
8888-|---|---|
8989-| `pnpm dev` | Start dev server |
9090-| `pnpm build` | Build for production |
9191-| `pnpm check` | Run svelte-check |
9292-| `pnpm env:generate-key` | Generate client assertion key |
9393-| `pnpm env:generate-secret` | Generate cookie signing secret |
9494-| `pnpm env:setup-dev` | Generate both and write to `.env` |
1414+See [GETTING_STARTED.md](GETTING_STARTED.md) for production deployment, tunnel setup, and configuration.
95159616## Adding to an existing project
9717···10121add atproto oauth to this project https://raw.githubusercontent.com/flo-bit/svelte-atproto-oauth-cloudflare-workers/main/AGENT_SETUP.md
10222```
10323104104-The [agent prompt](AGENT_SETUP.md) will ask you a few questions and set everything up.
2424+The [agent prompt](AGENT_SETUP.md) asks a few questions and sets everything up.
1052510626**Manually** — see [SETUP.md](SETUP.md) for a step-by-step guide.
10727