Preview GitHub Gists as live web pages.
https://gists.page/<gist_id>/
A static shell plus a Service Worker — no backend, no build step, no account, nothing stored. The visitor's browser fetches gist content straight from GitHub (their own connection, their own rate limit) and renders it with correct MIME types.
- Runs HTML demos as live pages —
index.html(or an HTML first file) becomes a real page. Relative references between gist files (./app.js,./style.css, images) just work; gists are flat, so directory-style paths like./css/style.cssfold onto their basename automatically. Best fed a single self-containedindex.htmlwith inline JS/CSS. - Renders markdown like GitHub — GFM via markdown-it (sanitized with DOMPurify), syntax highlighting, mermaid diagrams, and KaTeX math.
- Shows source with line numbers — a GitHub-style blob view for code files; images display inline; binary formats get a "not shown" note with a raw link.
- Multi-file overview — gists without an HTML entry render every file stacked, like the gist page.
- Accepts every gist id — modern 32-hex ids, historical 16–40 hex ids, and old short numeric ids.
- Stays up when the API doesn't — falls back to cached metadata, then to the quota-free raw endpoint when the gist API is rate-limited or answers 502 (as it does for very popular gists).
| URL | Serves |
|---|---|
/<gist_id>/ |
index.html (or HTML first file); else an overview of all files |
/<gist_id>/<file_name> |
that file — rendered or highlighted on navigation, raw bytes for subresources |
Edits to a gist show up within 5 minutes (visitor-side metadata cache).
- https://gists.page/0152d8bc733b68dad27a477d0b45b3cd/
- https://gists.page/ee5d5136cc25c9f0e835308d3422e6e1/
- https://gists.page/8599e4e8ca705edd68521c3e538eca22/
- https://gists.page/1f32d84cd2f9bf79c307d51dbe7b047f/
index.html— landing shell. Registers the SW; when a navigation bypassed the SW (first visit, hard refresh), re-navigates once so the SW can serve real content, with a navigation-type-based guard against reload loops.sw.js— intercepts same-origin/<gist_id>/<file>GETs, fetches gist metadata from the GitHub API (5-minute in-SW-memory cache — deliberately not CacheStorage, which same-origin pages could poison), streams binary/truncated files from raw URLs, serves the viewer shell for non-HTML navigations, falls back to the quota-free raw endpoint when the API is unavailable, and attaches security headers to every synthesized response.viewer.html— client-side viewer for non-HTML files: GitHub-flavored markdown (markdown-it + DOMPurify), syntax highlighting (highlight.js), mermaid diagrams, and KaTeX math, loaded from jsDelivr at view time._redirects— explicit SPA fallback (/* /index.html 200) so gist deep links always reach the shell, even if a404.htmlis ever added._headers— security headers for statically served responses.
npx wrangler pages dev . # local devProduction is a git-connected Cloudflare Pages project — no build command,
output directory / — so every push to main deploys. To ship from a
terminal instead: npx wrangler pages deploy ..
Plain static files — any host with an SPA fallback works; _redirects and
_headers are in Cloudflare Pages format. Note: the Workers static-assets
channel (wrangler deploy --assets) is not equivalent — its stricter
_redirects validator rejects the SPA rule, and it uploads .git/ as public
assets unless told otherwise.
Keep the origin dedicated to previews: gist code runs same-origin, so don't host this on a subdomain that shares cookies with anything that matters.
- Nothing is stored or proxied; content flows from GitHub to the visitor's browser.
- Secret gists are unlisted, not private — anyone with the link can view. Never put keys, tokens, or internal data in a gist.
- The preview origin carries no cookies or accounts, and rendered markdown is sanitized. HTML gists run as-is, like on any static host.
skills/ holds agent skills — SKILL.md instruction sets any
SKILL.md-aware AI agent can install. They teach an agent this service's exact
rules: single-file-first authoring, flat-file limits, basename folding, caching
behavior, URL formats, and how to publish demos with whatever the session has —
gh CLI, GitHub MCP tools, or the REST API with a token.
| Skill | Teaches |
|---|---|
gists-page |
Publish HTML/JS/CSS demos as gists and share gists.page preview links |
Each skill is a single self-contained folder — a SKILL.md with YAML
frontmatter (name, description) and a markdown body — following the
Agent Skills open standard. Installing is copying
that folder into a directory your agent scans; the frontmatter description
is what makes the agent reach for it on its own.
gists-page is published to ClawHub:
openclaw skills install @zzir/gists-pageOr copy the folder out of this repo yourself — that's all installing is.
mkdir -p ~/.claude/skills
cp -r skills/gists-page ~/.claude/skills/Claude Code watches both directories and picks up the new skill within the
running session — restart only if the skills/ directory didn't exist when
the session started. Then use it either way:
- Automatically — say what you want ("publish this demo and give me a shareable link") and Claude loads the skill when your request matches the description.
- Explicitly — type
/gists-pageto invoke it by name.
Codex scans .agents/skills/ from the working directory up to the repo root,
then ~/.agents/skills/:
mkdir -p ~/.agents/skills
cp -r skills/gists-page ~/.agents/skills/Restart Codex, then /skills lists what loaded. Invoke explicitly with
$gists-page in the CLI or IDE extension (@gists-page in ChatGPT), or just
describe the task and let Codex match it. To turn a skill off without deleting
it, add to ~/.codex/config.toml:
[[skills.config]]
path = "/path/to/gists-page/SKILL.md"
enabled = falseThe skill covers publishing and updating, so prompts like these go end to end:
- "Publish this page as a gist and give me the gists.page link"
- "Turn this snippet into a live demo I can share"
- "Update the gist with my edits, then check the preview"
It will pick a publishing path from whatever the session already has — an
authenticated gh CLI, GitHub MCP gist tools, or curl with a
$GH_TOKEN/$GITHUB_TOKEN carrying the gist scope. With none of those, it
asks you to paste the files into https://gist.github.com and hand back the id.
Nothing here needs the service itself to be installed or configured.
Issues and PRs welcome — it's a deliberately small codebase: one worker, one viewer, one shell.