A small, private collection of self-contained web pages — plans, reports, explainers — that you hand to someone (or their agent) as a single link. Branded, visual, and live in one command.
One folder, one HTML file, one URL — served from a single static site, grouped by project.
Every shareable is a self-contained HTML page (its CSS, SVG, and logic inline; diagrams pulled from a CDN). There's no build step and no framework — which means it renders the same on anyone's machine, years from now, with nothing to install. Pages live at:
https://shareables.yahyatarique.dev/<project>/<slug>
They're grouped by project on the homepage (LetsGetVisa, Voxforce, Personal…), each with a searchable, auto-generated index. The page you're reading is itself a shareable in the Shareables project.
Two layers of brand: the site identity (this page), and each project's identity (its pages).
The coaster-stack logo in the header — three stacked rounded cards with a “share” node-and-edges glyph — is the site's own identity. It's the favicon, the homepage mark, and the badge on every OG preview card. Gold gradient #F4A261 → #C1804D on dark navy #0b1120.
A page about a product wears that product's brand — its logo, its colours, its header. We detect the project's identity from its codebase (logo files, theme variables) and theme the header, accents, and even the diagrams to match.
The shortcut: copy the <head>/<style> + header from a sibling page already in that project and swap the content. E.g. LetsGetVisa pages share a navy #1B365D + gold palette.
Projects can register a logo in shareables.json under projects. Opt-in only — unregistered projects show initials on a tinted chip.
Use logo (SVG path) or emoji (single emoji character) — emoji wins if both are set. Logo/emoji icons render without a background box; initials fallback keeps the tinted chip.
{
"projects": {
"LetsGetVisa": { "logo": "logo.svg", "accent": "#F4A261" },
"PPTBuilder": { "emoji": "📑", "accent": "#F4A261" }
},
"items": [ … ]
} Logo SVGs live at projects/<project-slug>/logo.svg. Run node build-index.cjs — icons appear on homepage headers, project breadcrumbs, and command-bar results (bare, no tile background).
Diagrams via Mermaid (drawn in-page from a CDN), and data as hand-rolled inline SVG when a picture beats a paragraph.
Include the Mermaid CDN once and write diagrams as text; they render on load, themed to the brand. The wiring diagram above is one. Here's the publish pipeline as a sequence:
For real numbers, a small inline SVG bar chart drops straight in. This one is live data: pages currently published per project.
No chart library — just rectangles and text. Update the heights, keep the file self-contained.
<details> sections (like this), copy-to-clipboard buttons, status pills (REQUIRED OPTIONAL), the timeline below, and persisted task checkboxes via localStorage. Anything that helps the reader skim — as long as it stays inline.Each page carries a real last-updated stamp, and a page can show its own history inline.
The manifest stores an updated field per page, and the homepage cards show each page's real date/time (from the file's mtime) — so the collection reads as a living log, newest first. Inside a page, a simple timeline captures how the thing it documents evolved. Here's the shareables system's own:
og:auto meta, so links unfurl nicely.--force re-renders all.publish.mjs. One command: copy → manifest → build → OG → push → verify URL.shareables skill. Out of search results; the whole workflow packaged as a reusable skill across agents.lgv:, >, @); j/k on listings; [/] between pages; copy link on leaf pages; ? help. Catalog UI loads only when logged in — public share links stay bare.On the catalog (homepage and project listings) when logged in, and on leaf pages after login. Press ? anytime for the cheatsheet. Anonymous visitors on a public share link get the page only — no command bar or prev/next.
Spotlight-style palette: fuzzy search over pages and projects, quick actions, and your last eight picks (pages, project listings, home, and actions — stored in localStorage). Results rank by recency when the query is empty; typing filters live. A context strip shows where you are (catalog, project, or current page).
| Key | In the command bar |
|---|---|
| ↑ ↓ | Move selection |
| ↵ | Open selection (same tab) |
| ⌘⇧C | Copy link for the selected page or project |
| Esc | Close and clear the grid filter on index pages |
Scoped search: prefix the query to narrow results — lgv: / ppt: / vf: (project pages), > (actions only, e.g. > home or > theme), @ (projects only). On leaf pages, actions include Copy link to this page, go home, project index, and prev/next when the catalog is available.
Actions also include Toggle appearance (light/dark catalog theme; same preference as the header button on index pages). When you have recent visits, Clear recent history appears under Actions. On index pages, search also filters the card grid behind the palette.
| Key | Index (homepage / project) | Leaf page (logged in) |
|---|---|---|
| j ↓ | Next card | Next page in project |
| k ↑ | Previous card | Previous page in project |
| Enter | Open focused card | — |
| ⌘K / | Command bar — search pages & projects | Command bar — search, home, prev/next, copy link |
| [ ] | — | Prev / next (same as k / j) |
| h | — | Home |
| b | — | Project index |
| Esc | Close command bar / clear focus / close help | Close command bar / close help |
| ? | Shortcuts cheatsheet | |
Cards show the same OG image as link previews (lazy-loaded, browser-cached). Once loaded, the title hides — the image carries it — and only the page slug chip remains (project context is in the section header). Overlay UI (command bar, leaf nav bar, help sheet) mounts in an isolated shadow root so leaf-page CSS cannot break it. The searchable catalog and prev/next require login — public and private share links stay open to anyone with the URL; logged-in users get the full nav via a session check.
Write the HTML in your scratchpad, then publish. The command does everything and prints the live URL.
node ~/.claude/scratchpad/.shareables/scripts/publish.mjs \ --file ~/.claude/scratchpad/<page>.html \ --project "LetsGetVisa" \ --title "Human Title" \ --desc "One-line summary for the card + link preview."
| Flag | Meaning | |
|---|---|---|
--file | REQUIRED | Path to the self-contained HTML. |
--project | REQUIRED | Groups the page on the homepage. Never inferred — so a page can't land in the wrong group. |
--title | REQUIRED | Shown on the card and the link preview. |
--desc | OPTIONAL | One-line summary for the card + OG description. |
--slug | OPTIONAL | URL name; defaults to the filename. Reuse the same slug to update the same link. |
--private | OPTIONAL | Require login to view this page (--public clears it). |
--live | OPTIONAL | Enable the live KV store (votes/flags/counters) for this page (--static clears it). |
--dry-run | OPTIONAL | Run every local step but stop before commit/push — preview what would change. |
shareables skill knows this whole workflow — including not to hand-write OG meta (the generator owns it) and to ask which project if it's ambiguous.<project>/<slug>/index.html → upsert shareables.json → build-index.js (homepage + project listings) → generate-og.mjs (card + meta) → git commit + push (Vercel deploys) → poll the URL and print ✅ Live. OG images are not generated on deploy, which is exactly why the publish step runs the generator for you.Pages are static by default — but any page can opt into a shared key-value store for votes, flags, reactions, counters, RSVPs, or polls that update live across visitors.
The store is a Vercel Edge function (api/flags.js) backed by Upstash KV. Each live page gets a namespace of itemId → { count, mine, voters:[{ name, ts, loc }] }; a voter is keyed by sha256(email) of the signed-in account so a click toggles instead of double-counting, and coarse IP geo is captured at the edge (works on Vercel's free Hobby plan). Actions require a signed-in account (admin or a self-serve visitor account) — no anonymous voting.
Publish with --live (or set "live": true on its shareables.json entry). build-index.cjs compiles every live page into lib/live-pages.js — the store's write allowlist, so the KV stays scoped and clean. The pageId is <projectSlug>-<slug>.
lib/live-kv.js handles fetch, identity (whoami), polling, toggling, and the onAuthRequired redirect to /login. Needs Upstash env vars (KV_REST_API_URL, KV_REST_API_TOKEN) plus SHAREABLES_SESSION_SECRET for accounts — without KV the endpoint returns 501 and the rest of the site is unaffected.
import { createLiveStore } from "/lib/live-kv.js"; const store = createLiveStore({ page: "voxforce-account-triage", onAuthRequired: () => location.href = store.loginUrl() }); // send to /login on 401 const me = await store.whoami(); // { loggedIn, role, name, email } | null store.subscribe((flags) => render(flags)); // live updates (polls every 8s) await store.toggle("item-1"); // flag/unflag for the signed-in account
The Account Triage tool is a live page built this way — masked emails, sign-in-to-vote, and a tally that updates as teammates vote. get / flag / unflag / toggle / subscribe / whoami / loginUrl are the whole API. Voters sign in with an admin or self-serve visitor account; IPs and emails are recorded server-side but never returned to clients.
These are private share links — not secret, but not meant to surface in search. So we keep them out of search-engine results with a X-Robots-Tag: noindex, noarchive header, and that's it.
We deliberately don't block crawlers or AI bots. The whole point is that you hand a teammate a link and their tools — including their coding agents — can open and read the doc. No-index, not no-access.
Like it? Stand up your own — branded pages, OG previews, one-command publish — on your own domain in about ten minutes.
The setup page has harness tabs for Cursor and Claude Code (/publish + skill), plus a step-by-step walkthrough (Vercel + git). The kit is genericized — your domain swapped for a placeholder, so it's yours to brand.