Skip to main content
← All docs
UUsable
    usable

    Authoring and publishing documentation

    Updated 2026-07-07

    |Open in||History

    How this docs site works

    Each page you read on docs.usable.dev (or /usable/... locally) is a published memory fragment in a Usable workspace. The Next.js app does not store copy in Git — it renders live content from the Usable API, caches it for performance, and refreshes when fragments change.

    At a high level:

    1. Authors edit markdown + YAML frontmatter in Usable.
    2. Media lives in Usable Assets and is referenced with asset:// URIs in markdown.
    3. The docs app fetches fragments, resolves assets to CDN URLs, and renders MDX + Shiki for HTML pages.
    4. On-demand revalidation busts the cache when content is published or updated.

    The diagram below is stored in Usable Assets under the Usable Docs → Testing folder (same tenant as this workspace):

    Illustration used for docs pipeline smoke tests

    Tip for authors: If the image does not appear, confirm USABLE_ASSETS_API_KEY is configured on the docs server and that the asset ID in asset://usable-assets/<uuid> matches the image in Assets.

    Frontmatter contract

    Every doc fragment should include frontmatter like this:

    ---
    slug: authoring-and-publishing
    section: Getting Started
    order: 2
    status: published   # draft fragments are hidden from the public site
    description: >
      One or two sentences for SEO, llms.txt, and search snippets.
    ---
    FieldRequiredPurpose
    slugRecommendedURL path under the tenant (/usable/<slug>)
    statusYespublished or draft
    orderRecommendedSort order inside a section or collection
    descriptionRecommendedShown in metadata and LLM manifests

    Referencing images from Usable Assets

    Use the asset:// scheme in markdown. The renderer replaces it with a signed CDN URL at request time:

    ![Alt text](https://usableassets.blob.core.windows.net/assets-dev/b2a02e7b-fc4d-6fbf-33cf-1f44fcb8e994/images/transforms/cfbe34db-6851-4772-a80e-64b3ac57587c/w1600.webp?sv=2025-11-05&spr=https&st=2026-07-12T17%3A37%3A55Z&se=2026-07-12T18%3A37%3A55Z&sr=b&sp=r&sig=YHo9Y73Ym4fWKAtEtZP8LKPv7RatTgZc9N3XVKDHcts%3D)

    The same resolved URL appears in the .md variant of the page for LLM consumers.

    Example: trigger cache refresh after publish

    When a fragment changes, call the docs webhook (or /api/revalidate) with your secret:

    curl -sS -X POST "http://localhost:3000/api/webhooks/usable" \
      -H "Authorization: Bearer $REVALIDATE_SECRET" \
      -H "Content-Type: application/json" \
      -d '{
        "workspaceId": "ef680c43-c6a2-4897-9470-4cf6d3bb204e",
        "tenant": "usable",
        "slug": ["authoring-and-publishing"]
      }'

    On the server, revalidation is implemented roughly like this:

    import { revalidateTag, revalidatePath } from "next/cache";
     
    export async function refreshTenantPage(tenant: string, slug: string[]) {
      revalidateTag(`docs:tenant:${tenant}`, "max");
      revalidatePath(`/${tenant}/${slug.join("/")}`);
    }

    Code samples in docs

    Syntax highlighting uses Shiki (VS Code themes). Fenced blocks need a language tag:

    type DocFrontmatter = {
      slug: string;
      status: "published" | "draft";
      order: number;
    };
     
    export function isPublic(doc: DocFrontmatter): boolean {
      return doc.status === "published";
    }
    {
      "ok": true,
      "revalidated": {
        "tenantTag": "docs:tenant:usable",
        "paths": { "tenantPage": "/usable/authoring-and-publishing" }
      }
    }

    What to try next

    • View this page as raw markdown: /usable/authoring-and-publishing.md
    • Check the tenant manifest: /usable/llms.txt
    • Edit this fragment in Usable, revalidate, and refresh to see ISR in action