The same app runs on Cloudflare Workers — for when agents run on a different machine than the browser, or you want the viewer on your phone.
npx wrangler login
npx wrangler secret put SIDESHOW_TOKEN # any long random string
npm run deploy # https://sideshow.<account>.workers.devA deployed instance requires the token on every request. Open the viewer once as
/?key=<token> to set a cookie. Agents need two environment variables; the CLI
and stdio MCP pick them up automatically:
export SIDESHOW_URL=https://sideshow.<account>.workers.dev
export SIDESHOW_TOKEN=<token>To share read-only access without handing out the token, set
SIDESHOW_PUBLIC_READ on the deployment:
SIDESHOW_PUBLIC_READ=sessionmakes direct/session/:idlinks readable without a token while keeping/and the session list private (unlisted-link style).SIDESHOW_PUBLIC_READ=fullmakes all read routes public, including the root viewer and session list.
Writes still require SIDESHOW_TOKEN, and authenticated owners keep the full
UI. Invalid SIDESHOW_PUBLIC_READ values are ignored.
Bare post links (/s/:postId) include Open Graph/Twitter metadata for inline
previews. Crawlers only see useful previews when those read routes are publicly
reachable under the settings above; tokened/private workspaces do not put
?key= secrets into preview metadata. Preview images use
/s/:postId.png?card=1, which requires the Cloudflare Browser Rendering binding
from wrangler.jsonc on deployed Workers.
Remote agents can connect MCP straight to the deployment:
claude mcp add --transport http sideshow https://sideshow.<account>.workers.dev/mcp \
--header "Authorization: Bearer $SIDESHOW_TOKEN"A post's first renderable surface can be rendered to a PNG at /s/:postId.png
(the viewer's "open first surface as image" action links here; ?card=1
produces the 1200×630 Open Graph/Twitter preview image embedded in /s/:postId
link unfurls). The image is captured by a real headless browser through
Cloudflare's Browser
Rendering binding, declared
in wrangler.jsonc:
Because there is no headless browser on the plain Node server, /s/:id.png is a
Workers-only route. The local viewer still shows the screenshot action, but
disabled with a tooltip — there is nothing to render the image. Auth is unchanged:
the Worker first forwards the request to the post's read route, so a private
workspace's screenshots stay as protected as the workspace itself.
The whole app runs inside a single Durable Object with SQLite storage. One instance per workspace keeps the in-memory event bus authoritative, so SSE and long-polling behave the same as the local server.