Pagelet/ docs
Docs menu

Capabilities

Two capability surfaces — the service manifest and the runtime contract — and how to feature-detect.

Two surfaces, two questions

SurfaceAnswersFormat
GET https://pagelet.link/api/capabilities"What can the service do right now?" — which optional features are enabled in this deploymentJSON, cache-control: no-store (never cached — it is the runtime truth)
GET https://cdn.pagelet.link/v1/capabilities.md"What can the runtime do?" — the authoring contract every pagelet gets from the one tagMarkdown with a YAML front-matter manifest, no-cache (revalidates)

Docs describe design; the manifest is the runtime truth. Read the service manifest before offering anything optional — email login, claim, private artifacts, cloud PDF, SSO, billing, custom domains, notebooks. When a flag is false, the feature fails closed server-side; skip it gracefully and don't promise it.

The service manifest

GET /api/capabilities — illustrative values
curl -sS https://pagelet.link/api/capabilities
{
  "schema": 1,
  "service": {
    "cloud_publish": true,
    "url_scanning": true,
    "cloud_pdf": true,
    "accounts": true,
    "claim": true,
    "web_login": true,
    "password_login": true,
    "sso": { "google": false, "github": false, "microsoft": false },
    "dashboard_mutations": true,
    "mcp": true,
    "live_dashboards": true,
    "versioning": true,
    "pro": false,
    "private_artifacts": true,
    "brand_extract": false,
    "custom_domains": false,
    "notebooks": true
  },
  "runtime": "https://cdn.pagelet.link/v1/",
  "default_expiry_days": 30,
  "abuse_contact": "mailto:abuse@pagelet.link"
}
FlagMeaning when true
cloud_publishHosted delivery is available (POST /api/upload, MCP publish_pagelet). The cloud-default delivery policy keys off this.
url_scanningThe async URL-scanner pipeline is configured (publish + every new version is scanned).
cloud_pdfBrowser Rendering is configured — /api/pdf, render_pdf and seals work.
accountsAgent registration exists (always true).
claimEmail delivery is configured, so the claim OTP can actually be sent. Check before offering claim to a human.
web_loginEmail-OTP dashboard sign-in (needs email + session key).
password_loginPassword sign-in (needs only the session key).
sso.{google,github,microsoft}Per-provider social sign-in — on only when that provider's OAuth keys are set.
dashboard_mutationsOwners can rename / re-expire / delete / set visibility from the dashboard API.
mcpThe MCP server is up (always true).
live_dashboardsrender_dashboard / POST /api/dashboards (always true).
versioningRepublish-in-place, ?v=N pins, /__version polling (always true).
proStripe billing is configured.
private_artifactsThe per-artifact password gate is enabled (launch flag).
brand_extractFirecrawl brand-scrape → theme (extract_brand, /api/brand).
custom_domainsOwner hostname mapping is enabled.
notebooksHosted notebooks (always true).

runtime is the runtime base URL, default_expiry_days the anonymous default (30),abuse_contact where reports go. The same JSON is served by the MCPget_capabilities tool and the pagelet://capabilities resource.

The runtime contract

The capability doc is served next to the runtime and versioned with it — agents fetch it and follow it, so the menu updates server-side with no reinstall. Its front matter is the machine-readable part:

cdn.pagelet.link/v1/capabilities.md
curl -sS https://cdn.pagelet.link/v1/capabilities.md
# ---
# schema: 1
# runtime_version: "0.2.5"
# base_url: "https://cdn.pagelet.link/v1/"
# capabilities: [markdown, mermaid, math, code, charts, theme, toolbar, toc, interactive, versions]
# status: alpha
# ---
# …followed by the full authoring contract for each capability
CapabilityStatusContract in one line
markdownstable<script type="text/markdown" data-pagelet="markdown"> → rendered, sanitised prose; source kept for round-trip export.
mermaidstable```mermaid fenced blocks or <pre class="mermaid"> → SVG with pan/zoom/fullscreen.
mathstableKaTeX. $$…$$ and \[…\] display, \(…\) inline. Single-$ inline is OFF (currency collisions).
codestableFenced language blocks → highlight.js + copy button, theme-aware.
chartsstable<script type="application/json" data-pagelet="chart"> with a Chart.js config → themed responsive canvas.
themestabledata-pagelet="theme" JSON → shadcn-named CSS variables; auto/light/dark modes; pagelet:themechange event.
toolbar & tocstableFloating toolbar (theme, PDF, PNG, copy-as-Markdown, version history — draggable + collapsible); scroll-spy TOC at ≥3 headings. Off with <body data-pagelet-toolbar="off">.
interactivealphadata-pagelet-interactive → shared layout + state→preview→prompt pipeline API; wait for pagelet:interactive-ready.
versionsstableHosted pages poll same-origin /__version → refresh toast; toolbar timeline; ?v=N pins.

Each module is lazy-loaded — a page only fetches what it uses. Versioning rule: the rolling/v1/ channel is strictly backward-compatible; immutable exact pins live at/v1.x.y/; a breaking re-architecture would ship as /v2/, so old artifacts never break.

How to feature-detect

  1. Before authoring — fetch /v1/capabilities.md for the authoring contract (or rely on the skill, which teaches the same protocol).
  2. Before offering a hosted feature — check the matching service.* flag in /api/capabilities. True → proceed; false → deliver locally / skip the offer, and say why.
  3. Before promising a link — publish, then fetch the returned URL once and confirm 200 + your HTML. Only then hand it over.
  4. Never cache the manifest — it's no-store on purpose; a stale copy advertises features that may have been switched off.

The version-metadata invariant: an artifact page can only learn about itself same-origin (/__version, /__versions, /__pdf on its own origin — the artifact CSP allows only 'self'), and those endpoints always apply the page's own gates (blocked → 451, expired → 410, private → access cookie). Service-side, versioning: true tells you the whole loop exists. Neither side ever leaks update activity across the isolation boundary.