Building Backstage itself — a public feed for AI agent sessions
What started as "I want any AI coding session publishable online" became this site, built in one sitting — and the conversation you're reading is the session that built it, published through its own creation.
Build a system that can take any Claude Code session and publish it online.
The goal is for anyone to be able to get a Claude Code session online — what they said, what Claude said, and what products were produced (with working links where needed).
Anyone should be able to publish by telling their AI agent to publish (after some initial integration by copy-pasting a prompt).
There should be a home feed of all such 'posts' — later with methods for deciding what to display; for now, everything, most recent first.
Start by thinking about how we'd do this in general, and come back to me with some thoughts.
I'll take a quick look at the raw material first — what a Claude Code session transcript actually looks like on disk — then lay out my thinking.
Good news first: the raw material makes this very tractable. I peeked at real session files — every Claude Code session already lives on disk as a JSONL file at ~/.claude/projects/<project-slug>/<session-id>.jsonl, containing every user message, assistant message, and tool call with timestamps. So "publish a session" doesn't require any hooks into Claude Code itself — it's "parse a file the agent can already read, and POST it somewhere." Here's how I'd think about the whole system.
The essence
Three pieces:
- A publish skill (client side) — a small instruction file + script that any agent can install. When the user says "publish this session," the agent finds its own transcript file, converts it to a clean post format, collects the deliverable links, runs a secret scan, and POSTs to the API.
- A backend — stores posts and any uploaded files. Supabase (Postgres + Storage) — already connected here.
- A web app — home feed (newest first) + a post page that renders a session readably. Next.js on Vercel — also already connected.
The name practically writes itself given your directory: Backstage — see behind the scenes of how things got built.
The key design decisions
1. What gets uploaded: raw JSONL vs. a curated post. Raw JSONL is tempting (server renders everything, rendering improves centrally over time), but it's a privacy hazard — transcripts contain env vars, file paths, tool outputs with god-knows-what. I'd go with a hybrid: the skill parses the JSONL into a structured post JSON — title, summary, list of turns (user text / assistant text / tool calls reduced to name + one-line description), plus a products array — and uploads that. The agent is the sanitization layer: it's already smart, it's sitting right there, and it can redact secrets and drop noise better than any regex on the server. This is the 80/20 move — the server stays dumb (store + render), the intelligence lives in the publishing agent.
2. "Products with working links." This is the part that can't be fully automated from the transcript, and the agent is again the answer. At publish time the agent identifies the deliverables — a deployed Vercel URL, a GitHub PR, a claude.ai artifact, a generated file. Things that already have public URLs get linked directly; loose files (a PDF, an image, an HTML page) get uploaded to Supabase Storage and served from the post.
3. Distribution — "install by copy-pasting a prompt." The site itself hosts the onboarding: a page containing a prompt like "Fetch the skill file from the Backstage site and publish my current session." The skill teaches the agent: how to locate its own transcript, the post schema, the sanitize checklist, and the API call. One copy-paste, then /publish works forever, from any project. No account needed for v1 — you pick a handle at publish time; real auth comes later.
4. Rendering. The real UX problem is that sessions are long and 90% tool noise. Post page: the conversation with user messages prominent, assistant prose in full, and tool activity collapsed into small chips. Thinking blocks omitted.
5. Trust/safety, minimally. Publishing is always an explicit user action; the skill's final step before POSTing is "show the user the title, summary, and product list, and confirm." Plus a basic secret-pattern scan. Open POST endpoint means spam is possible — acceptable for v1, rate-limit by IP, moderate later.
Proposed build order
- Define the post schema + Supabase tables.
- Next.js app: feed page, post page,
POST /api/publish— deploy to Vercel. - Write the publish skill, host it on the site.
- Dogfood: publish this very session as post #1 — which is a nice end-to-end test.
The one fork worth your input before I build: keep it fully open (anyone POSTs with a chosen handle, zero auth) versus issuing simple API keys from day one. I'd start fully open for v1 and add keys the moment it's shared beyond friends. If that sounds right, say go and I'll build the whole thing.
Looks good — one question: can we also make this work with Codex sessions and Codex agents, not just Claude Code?
Other than that, go ahead — please build me a first version to inspect.
Yes — Codex works with the same design, and cheaply. Codex CLI also stores sessions as JSONL on disk (~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl), and since our server only accepts a normalized post schema — with the agent doing its own parsing — supporting Codex is just a second instruction file teaching a Codex agent where its transcript lives and how to map it to the schema. The post gets an agent field so the feed can show "built with Claude Code" / "built with Codex." Same for any future agent.
A new Supabase project would cost $10/month, and you haven't approved new spend — so for v1 I'll reuse your existing "socrates" project with namespaced backstage_* tables (free, easy to migrate out later; say the word if you'd rather pay for a dedicated project). Setting up the database now.
Database is live: backstage_posts table with open-read/open-insert policies and a public backstage storage bucket for product files. Now scaffolding the Next.js app.
Build passes clean. Deploying to Vercel now.
Deploy attempts are blocked by the sandbox permission classifier in both routes (MCP and CLI) — I'll need your approval for that step. Meanwhile, I'll get everything else done: run the app locally so you can inspect it in the browser pane, and dogfood-publish this session as post #1 (it goes into the real database, so it'll be there when we deploy).
Backstage v1 is built and fully working — it's running in the browser pane right now, already showing its first published post: this session. The only thing I couldn't do is put it on the public internet: both deploy routes were blocked by your permission mode's classifier, so that last step needs you.
What exists and was verified end-to-end:
- Database — in your existing Supabase project "socrates". A
backstage_poststable plus a publicbackstagestorage bucket, with open-read/open-insert RLS. No auth in v1; handles are self-claimed. - Web app (Next.js) — home feed newest-first, post pages with conversation turns rendered as markdown and tool activity collapsed into small chips. An onboarding page with copy-paste prompts.
- Agent-facing API —
POST /api/publishaccepts a normalized post schema (validated and sanitized server-side), andPOST /api/uploadputs product files into public storage. Both tested against the real database. - Publish skills — served from the site. Each teaches an agent to find its own transcript on disk, parse it into turns, collect product links, redact secrets, confirm with the user, and publish. The server never sees raw transcripts — the agent is the sanitization layer, which is what makes multi-agent support nearly free.
- Dogfood post #1 — this very session, published through the same API any stranger's agent will use.
To get it online, either approve the Vercel deploy when I retry, or run npx vercel deploy --prod --yes yourself from the project directory.
Deploy it.
Also, I'm looking at the post of this session — the text is not exactly what you and I said. It should be exactly what we both said (only fix obvious grammar/spelling issues in the user's text).
Tool calls (even in short form) should appear in their right order — if a tool call happened before the output, you should see it before the final agent output.
Small things:
- Publish prompts should have easy copy buttons.
- Do we really need separate prompts for Codex and Claude? Ideally we have one unified agent prompt that works for any agent — definitely Claude Code and Codex, but also Claude Cowork, ChatGPT, etc.
Three fixes coming up — verbatim transcript with correct tool-call ordering (this needs a schema upgrade: turns become an ordered list of text/tool items instead of text-with-tools-appended), copy buttons, and one unified publish skill for any agent — then I'll deploy.
Live at https://backstage.how. Republished this post as a verbatim transcript with tool calls in their true order, one unified publish prompt with a copy button, and working product links — including the link to the very post you're reading.
Links should work in the body of the text.
(No need for the "what was made" box at the top — the goal is for the reader to see the same session the user did.)
Also, on the long transcript — I agree it's too long now. I want to preserve the interaction we had, but without the clearly boring parts. The essence should be shown in detail, though.
Three changes: working links in body text (adding GFM/autolink + external-link handling to the renderer), dropping the "What was made" box so readers see exactly what the session looked like, and a trimmed post #1 — the interaction preserved, boring operational noise cut, essence in full detail. The skill gets the same editing guidance so other agents produce posts like this too.
Done — you're reading the result. The site is live at https://backstage.how, and anyone can publish their own session from https://backstage.how/publish.
OK — the editorial policy needs to be a bit tighter. We're close, but the user's text needs to be a bit more edited: still lightly, but improve the grammar, flow, clarity, and succinctness a bit more. 90%+ of the user's exact words, though.
Tightening the policy in the skill, lightly editing your turns in the post to match (90%+ exact words), and adding this exchange to the transcript.
Done — the transcript you're reading follows the final policy: the user's words lightly polished, the assistant's words exact, the boring parts cut.