Skip to content

garylesueur/showmeatsack.com

v0.1.0MIT

An agent posts HTML, markdown, or a small static-site zip and gets a showmeatsack.com view link. No API key. Free to publish; teams and custom domains are paid.

showmeatsack.com

An agent posts a page. A person opens it.

An agent publishes HTML, markdown, or a small static-site zip, and gets a view link to share. Anyone with that link sees the page itself. The same call returns a manage token to replace or delete the share; otherwise it expires on its own. There is no API key. Create is open today. Publishing will later need a lanyard account; that account is free unless they want teams or a custom domain.

Posting the view link to Slack, email, or anywhere else is the calling agent's job.

Sibling project: askmeatsack.com — an agent asks, a human answers.

Quick start

pnpm install
pnpm env      # writes .env.local from the 1Password Development item
pnpm dev

No 1Password access? cp .env.example .env.local gets you a working local server. Leave Redis and R2 empty to stay on in-memory stores.

Commands

CommandDoes
pnpm devDev server, reads .env.local
pnpm dev:opDev server with secrets in-process, nothing written to disk
pnpm envWrite .env.local from the Development item
pnpm env:vercel preview|productionPush that item to the matching Vercel env
pnpm typecheckTypeScript
pnpm lintoxlint, plus the import-layer check
pnpm formatoxfmt
pnpm testVitest
pnpm buildProduction build

pnpm typecheck, pnpm format:check, pnpm lint, pnpm test and pnpm build are the merge gates — see .engineering/config.yaml, and .engineering/conventions.md for the conventions they enforce.

Hosts

Two origins, on purpose. Published pages are untrusted HTML, so they are served from a separate host and never share an origin with the product site.

OriginServes
https://showmeatsack.comThe product site and the API
https://s.showmeatsack.comView links — the published pages themselves

Add s.showmeatsack.com to the Vercel project so that host reaches this app.

Secrets

Three 1Password items live in the Agents vault: showmeatsack.com Development, showmeatsack.com Preview, and showmeatsack.com Production. Same field names, different values. Local work uses Development only; Preview and Production are pushed to Vercel and are not for a laptop.

Each deployed environment needs its own Redis (KV_REST_API_* or Upstash) and its own R2 bucket (R2_ACCOUNT_ID, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_BUCKET_NAME) so shares survive across instances. BLOB_READ_WRITE_TOKEN remains a fallback if R2 is unset.

.env.development.tpl, .env.preview.tpl, and .env.production.tpl hold op:// references only. .env.example is the empty placeholder. Never print .env contents and never commit secrets.

Where things live

PathWhat
specs/Product intent. Start at specs/sharing/pages/publishing.md
specs/site/discoverability.mdSEO, Open Graph, sitemap, robots, llms.txt
src/app/api/v1/shares/The HTTP API
src/app/mcp/The MCP server
src/app/s/[shareId]/Serving a published page
src/lib/shares.tsShare service — create, replace, delete, view
src/lib/zip-site.tsUnpacking and path-checking an uploaded zip
.engineering/config.yamlToolchain contract that calm-craft skills read
skills/showmeatsack/The skill — the source of truth, edit this one
.cursor/skills/showmeatsack/Generated copy for Cursor (pnpm sync:skill)
plugin.jsonAgent Plugin (open standard) identity
.cursor-plugin/plugin.jsonCursor Open Plugin manifest for this clone
src/lib/showmeatsack-skill.tsGenerated constant the site and MCP serve

calm-craft

This repository is built with calm-craft, our own MIT-licensed Agent Plugin. It is vendored as a submodule at .agents/plugins/calm-craft:

git submodule update --init --recursive

What it is. Three things that make coding agents produce work you can trust: specs as an addressable source of truth, a delivery loop that plans and then executes one reviewable chunk at a time, and code conventions decided once and enforced by lint wherever a machine can enforce them.

Why we use it. Most of the code here is written by agents, and an agent with no fixed source of truth will happily invent one. Specs in specs/ are that fixed point — they outlive any single session, so a change three weeks from now starts from what the product is meant to do rather than from whatever the last diff happened to leave behind. That matters more than usual here: this service takes arbitrary HTML from the internet and serves it back, so the rules about path handling, expiry, and origin isolation need somewhere durable to live. The separation calm-craft defends matters just as much — auditors report and never edit, planning is not allowed to double as execution, and one chunk is finished and verified before the next one starts.

It also happens to be ours, so every public repo we ship is a repo we are running our own tooling on.

.engineering/config.yaml is the contract every calm-craft skill reads — paths, gates, branch, ticket provider. Skills stay portable; this repo's specifics stay in config we own, so updating the plugin never clobbers our choices.

Not yet run here: conventions-decide, which writes .engineering/conventions.yaml. Until then this repo has no recorded convention decisions, and paths.conventions points at a file that does not exist.

Install

This repository is itself an Agent Plugin — the open standard for packaging agent tooling: plugin.json, mcp.json, and skills/ in one installable unit. Cursor also reads .cursor-plugin/plugin.json so this clone can be added as an Open Plugin from the local folder. .mcp.json exists for cursor.directory detection.

Install in Cursor from this clone. In Customize → Plugins, add an Open Plugin and choose this repository root (the folder that contains plugin.json). For local development you can also symlink it:

ln -s /path/to/showmeatsack ~/.cursor/plugins/local/showmeatsack.com

Then reload the window. The plugin carries the hosted MCP server and skills/showmeatsack/SKILL.md.

Or install from GitHub:

https://github.com/garylesueur/showmeatsack

Or install the MCP server on its own at https://showmeatsack.com/mcp. The tool works, and the server sends the same skill as its MCP instructions, so most clients still get the full brief. Clients that ignore instructions see only the tool description — prefer the plugin where you can.

Licence

MIT — see LICENSE.

Built by Gary Le Sueur.