+82
-6
notes/quickslice-migration.md
+82
-6
notes/quickslice-migration.md
···
53
53
<script src="https://cdn.jsdelivr.net/gh/bigmoves/quickslice@v0.17.3/quickslice-client-js/dist/quickslice-client.min.js"></script>
54
54
```
55
55
56
-
### 3. OAuth flow
56
+
### 3. the UI
57
57
58
-
quickslice handles the OAuth server side. the frontend just needs to:
58
+
since quickslice serves its own admin UI at the root path, we host our frontend separately on cloudflare pages. the frontend is vanilla JS - no framework, just a single `app.js` file.
59
+
60
+
**OAuth with quickslice-client-js**
59
61
60
-
1. create a client with `QuicksliceClient.create()`
61
-
2. call `client.signIn()` to start the flow
62
-
3. handle the callback (quickslice redirects back with auth tokens)
63
-
4. use `client.agent` for authenticated AT protocol operations
62
+
the `quickslice-client-js` library handles the OAuth flow in the browser:
63
+
64
+
```javascript
65
+
const client = await QuicksliceClient.create({
66
+
server: 'https://zzstoatzz-quickslice-status.fly.dev',
67
+
clientId: 'client_2mP9AwgVHkg1vaSpcWSsKw',
68
+
redirectUri: window.location.origin + '/',
69
+
});
70
+
71
+
// start login
72
+
await client.signIn(handle);
73
+
74
+
// after redirect, client.agent is authenticated
75
+
const { data } = await client.agent.getProfile({ actor: client.agent.session.did });
76
+
```
64
77
65
78
the redirect URI is just the root of your site (e.g., `https://status.zzstoatzz.io/`).
66
79
80
+
**GraphQL queries**
81
+
82
+
quickslice auto-generates a GraphQL API from your lexicons. querying status records looks like:
83
+
84
+
```javascript
85
+
const response = await fetch(`${CONFIG.server}/api/graphql`, {
86
+
method: 'POST',
87
+
headers: { 'Content-Type': 'application/json' },
88
+
body: JSON.stringify({
89
+
query: `
90
+
query GetStatuses($did: String!) {
91
+
ioZzstoatzzStatusRecords(
92
+
where: { did: { eq: $did } }
93
+
orderBy: { createdAt: DESC }
94
+
first: 50
95
+
) {
96
+
nodes { uri did emoji text createdAt }
97
+
}
98
+
}
99
+
`,
100
+
variables: { did }
101
+
})
102
+
});
103
+
```
104
+
105
+
no need to write resolvers or schema - it's all generated from the lexicon definitions.
106
+
67
107
## problems we hit
68
108
69
109
### the `sub` claim fix
···
134
174
│ AT Protocol │
135
175
│ (bluesky PDS, jetstream firehose) │
136
176
└─────────────────────────────────────────────────────────┘
177
+
```
178
+
179
+
## what quickslice eliminated
180
+
181
+
the rust backend was ~2000 lines of code handling:
182
+
183
+
- OAuth server implementation (PKCE + DPoP)
184
+
- jetstream consumer for firehose ingestion
185
+
- custom API endpoints for reading/writing statuses
186
+
- session management
187
+
- database queries
188
+
189
+
with quickslice, all of that is replaced by:
190
+
191
+
- a Dockerfile that builds quickslice from source
192
+
- a fly.toml with env vars
193
+
- two secrets
194
+
195
+
the frontend is still custom (~1200 lines), but the backend complexity is gone.
196
+
197
+
## deployment checklist
198
+
199
+
when deploying quickslice:
200
+
201
+
```bash
202
+
# 1. set required secrets
203
+
fly secrets set SECRET_KEY_BASE="$(openssl rand -base64 64 | tr -d '\n')"
204
+
fly secrets set OAUTH_SIGNING_KEY="$(goat key generate -t p256 | tail -1)"
205
+
206
+
# 2. deploy (builds from source, takes ~3 min)
207
+
fly deploy
208
+
209
+
# 3. in quickslice admin UI:
210
+
# - set domain authority (e.g., io.zzstoatzz)
211
+
# - add supported lexicons
212
+
# - register OAuth client with redirect URI
137
213
```
138
214
139
215
## key takeaways