quicksliced my status

remove rust implementation artifacts · zzstoatzz/status@3193e82

quickslice rewrite replaces the custom rust backend. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

(most of this was lockfile / not source code tbh)

a while ago, i forked @baileytownsend.dev 's wonderful rusty statusphere repo and added in a whole lotta bufo so it could serve as any atproto identity's personal status page. thanks bailey :D

then, yesterday @chadtmiller.com released quickslice !

and i thought:

hey i should be able to replace the rusty-statusphere-derivative backend for status.zzstoatzz.io with a quickslice instance!

i wasn't yet sure how to write/deploy a UI that consumes the quickslice instance, but i had already ran the quickslice server locally and figured out how to configure the /settings more or less:

upload my pre- existing lexicons

make a zip like zip -j lexicons.zip lexicons/*.json

upload it in Lexicon portion of the settings

set a domain authority

io.zzstoatzz

set supported oauth scopes (no transition:generic allowed!)

io.zzstoatzz.status.record

io.zzstoatzz.status.preferences

register an OAuth client

client name: {anything} (e.g. "status")

redirect URI (one per line)

https://status.zzstoatzz.io/

http://localhost:8000/ (for local dev)

scope (space delimited)

atproto

repo:io.zzstoatzz.status.record

repo:io.zzstoatzz.status.preferences

note previously, preferences were persisted in the sqlite db that my rust backend talked to so font/accent preferences stuck across devices, but during this refactor i realized i could just store them as a record! not sure what the meta for "hey i wanna store just a little somethin non-standard in the quickslice db" is quite yet

the config looks like this in the admin panel of my quickslice instance

backend secrets and config

the quickslice instance needed two secrets for OAuth to work:

fly secrets set SECRET_KEY_BASE="$(openssl rand -base64 64 | tr -d '\n')"
fly secrets set OAUTH_SIGNING_KEY="$(goat key generate -t p256 | tail -1)"

(i think?) the OAUTH_SIGNING_KEY should be just the multibase key (starts with z), not the full output from goat... that's what worked for me anyways, lmk if i am wrong about this!

without EXTERNAL_BASE_URL, quickslice uses 0.0.0.0:8080 in its OAuth client metadata, so go ahead and set it to your public URL:

[env]
EXTERNAL_BASE_URL = 'https://your-app.fly.dev'

i used this thread to figure this out

so then after a smol bug encounter where quickslice was not returning sub from the token endpoint (causing login to redirect back to a logged out state), i rather expediently had a quickslice instance that could (very quickly!) backfill all the status records! excellent!

now i just needed to rewrite (or have claude rewrite tbh) the UI to consume my new backend in a box!

the UI!

this part turned out to be easier than i thought!

your lexicons are the API! after uploading the lexicons, you can just write GraphQL queries from your front-end to get your data!

const response = await fetch(`https://your-quickslice.com/api/graphql`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
query: `
query GetStatuses($did: String!) {
ioZzstoatzzStatusRecords(
where: { did: { eq: $did } }
orderBy: { createdAt: DESC }
first: 50
) {
nodes { uri did actorHandle emoji text createdAt }
}
}
`,
variables: { did }
})
});

i just told claude to broadly replace the calls to my old rust server endpoints in the UI with graphQL calls.... and then i went in the admin panel and clicked "Backfill" (once or twice, since it seemed it didn't totally backfill the first time? not sure).

then quickslice-client-js handles the OAuth flow in the browser:

const client = await QuicksliceClient.create({
server: 'https://your-quickslice.com', // your quickslice instance
clientId: 'client_xxx', // from quickslice admin UI
redirectUri: window.location.origin + '/', // where OAuth redirects back
});

// start login
await client.signIn(handle);

// after redirect, client.agent is authenticated
const { data } = await client.agent.getProfile({ actor: client.agent.session.did });

the clientId comes from registering an OAuth client in the quickslice admin UI. the redirect URI should match what you registered.

since quickslice serves its own admin UI at the root, we host our frontend separately on cloudflare pages . the frontend is vanilla JS - no framework, just a single app.js file (i do backend by trade! shh)

this is what worked for me as i tried to figure this out! if you have suggestions for improvements, please leave a comment here!

once i had my new backend and cloudflare pages, i switched my CNAME for status.zzstoatzz.io to point at the new cloudflare page.

and i deleted my old rust/fly backend and bob was then my uncle!

the whole thing!

┌─────────────────────────────────────────────────────────┐
│ cloudflare pages │
│ status.zzstoatzz.io │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ index.html │ │ app.js │ │ styles.css │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────┘
│
│ GraphQL + OAuth
▼
┌─────────────────────────────────────────────────────────┐
│ fly.io │
│ zzstoatzz-quickslice-status.fly.dev │
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ quickslice │ │
│ │ • OAuth server (PKCE + DPoP) │ │
│ │ • GraphQL API (auto-generated from lexicons) │ │
│ │ • Jetstream consumer │ │
│ │ • SQLite database │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
│
│ Jetstream
▼
┌─────────────────────────────────────────────────────────┐
│ AT Protocol │
│ (bluesky PDS, jetstream firehose) │
└─────────────────────────────────────────────────────────┘

get sliced!

links!

status

GitHub - zzstoatzz/status: slack status, without the slack

slack status, without the slack. Contribute to zzstoatzz/status development by creating an account on GitHub.

quickslice - the framework

AT protocol OAuth - the spec

quickslice-client-js - frontend OAuth helper

thanks chad for reviewing a draft of this post!