Skip to content

Latest commit

 

History

History
140 lines (106 loc) · 5.67 KB

File metadata and controls

140 lines (106 loc) · 5.67 KB

Publishing

The core action in htmlbook is publish: shelve a document to a hosted URL. The same pipeline backs the MCP publish tool and the REST POST /api/docs route.

When to publish

Reach for publish whenever you've produced something the user will want to read on another device or share with someone — an HTML report or dashboard, a spec, notes, a write-up — instead of leaving it as a local .html / .md file. Don't publish scratch files the user didn't ask to keep; documents are private by default, but the library is still theirs to keep tidy.

The three formats (auto-detected)

You never declare a format. htmlbook classifies what you send:

You send Stored as Reader experience
Markdown source.md (source of truth) + rendered index.html Themed reader; downloadable + editable as Markdown
An <article class="hb-doc"> fragment (bare or inside a full HTML page) Sanitized fragment Themed reader: TOC, paper/sepia/dark, inline edit
Any other full HTML page Verbatim "bundle" Sandboxed iframe — own CSS/JS runs

Detection keys off a real <article class="hb-doc"> content root. A page that only mentions the tag in escaped code does not match, so a doc about htmlbook stays a bundle correctly.

Publish with the MCP tool

Markdown — easiest for prose:

{
  "tool": "publish",
  "project": "acme",
  "slug": "q3-review",
  "markdown": "# Q3 Review\n\nRevenue up 8% QoQ.\n\n## Highlights\n- New onboarding\n- Churn down to 2.1%"
}

An hb-doc HTML fragment — for rich layout:

{
  "tool": "publish",
  "project": "acme",
  "slug": "q3-dashboard",
  "html": "<article class=\"hb-doc\"><div class=\"hb-content\"><h1>Q3 Dashboard</h1><div class=\"hb-kpi-grid\"><div class=\"hb-kpi\"><div class=\"hb-kpi-label\">MRR</div><div class=\"hb-kpi-value\">$12.4k</div><div class=\"hb-kpi-delta up\">+8%</div></div></div></div></article>"
}

Pass exactly one of markdown or html. Markdown accidentally placed in html (no leading <) is rerouted to the markdown path automatically, so a slip still lands as a themed doc rather than a verbatim bundle.

The response gives you the owner reader link right away, and the share link once public:

shelved (hbdoc) · acme/q3-dashboard · v1 · read: https://htmlbook.io/app/p/acme/q3-dashboard
  private — set_access "public" for a share link

project & slug

  • project groups documents (a project lives in a workspace). Required for HTML. For Markdown it can come from the file's frontmatter instead — see markdown.md.
  • slug is the document's id within a project. Optional — it's derived from the title / first heading when omitted.

Publishing to an existing project/slug creates a new immutable version; it does not overwrite. Earlier versions stay restorable.

Idempotency

Publishing is idempotent by content hash. Re-pushing an unchanged document is a true no-op (no new version):

no change (hbdoc) · acme/q3-dashboard · v1 · read: https://htmlbook.io/app/p/acme/q3-dashboard

For Markdown the hash is over the original .md source, so re-running a folder sync is cheap.

Large documents — push the file, not the tokens

Re-emitting a long document inline costs your agent tokens twice (once to write it, once as the tool argument) and bloats its context. Instead, write it to a file and push the file over REST so only one line passes through your context:

curl -s -X POST "https://htmlbook.io/api/docs?project=acme&slug=q3-dashboard" \
  -H "Authorization: Bearer $HTMLBOOK_API_KEY" \
  --data-binary @dashboard.html

Same pipeline, same idempotency, same versioning. Full details in rest-api.md.

Full custom pages (bundles)

Anything that isn't an hb-doc — your own <style>, <script>, layout, a charting library — is stored verbatim and rendered in a sandboxed iframe. Scripts run; localStorage and inline handlers work because it's served from an isolated origin. There's no theming/TOC/inline-edit for a bundle. Just push the full page:

curl -s -X POST "https://htmlbook.io/api/docs?project=acme&slug=pricing-calculator" \
  -H "Authorization: Bearer $HTMLBOOK_API_KEY" \
  --data-binary @calculator.html

Multi-file bundles

A bundle can be more than one file — an index.html entry plus sub-pages and assets (CSS, JS, images, fonts), up to 10MB total / 100 files — so relative links between pages work like a tiny static site. Files upload directly to storage via a 3-step presigned REST flow (the document never passes through your agent's tokens):

# 1) init — declare the files; get a presigned PUT url for each
curl -s -X POST https://htmlbook.io/api/docs/bundle/init \
  -H "Authorization: Bearer $HTMLBOOK_API_KEY" -H "Content-Type: application/json" \
  -d '{"project":"acme","slug":"guide","files":[{"path":"index.html","bytes":1234},{"path":"css/app.css","bytes":567}]}'
# 2) PUT each file to its url (Content-Type must match the extension)
curl -s -X PUT "<url>" -H "Content-Type: text/html; charset=utf-8" --data-binary @index.html
# 3) commit
curl -s -X POST https://htmlbook.io/api/docs/bundle/commit \
  -H "Authorization: Bearer $HTMLBOOK_API_KEY" -H "Content-Type: application/json" \
  -d '{"uploadId":"<from-init>"}'

The bundle runs cross-origin: fetch/network and localStorage work, but it has no htmlbook session, requests must be https, and you should never embed secrets in the client JS (the source is visible). Multi-file bundles are read-only in the web reader — re-run init→commit to update.

See also: Markdown · hb-doc contract · Sharing