Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/cryguy/hashboard/llms.txt

Use this file to discover all available pages before exploring further.

Every resource URL in Hashboard — a board, a card, a standalone document — is a single canonical address that serves three different renditions depending on who is asking. A browser gets a rendered page. An agent or curl command gets markdown with structured frontmatter. A script gets JSON. The rendition is selected by the Accept header or by a .md suffix on the URL, and the choice is intercepted centrally in hooks.server.ts before any route handler runs.

The Three Renditions

Accept headerRenditionTypical consumer
text/htmlSSR’d SvelteKit pageBrowser
text/markdownMarkdown + YAML frontmatterAgent, curl, LLM tool
application/jsonSame composite JSON as the REST APIScript, programmatic client
The JSON rendition returns exactly the same composite payload as the corresponding REST API endpoint — GET /api/v1/boards/{id} and GET /boards/{id} with Accept: application/json are identical responses. There is no separate “view model.”

The .md Suffix

Appending .md to any resource URL forces the markdown rendition, regardless of the Accept header:
/boards/9f4a1c2e-83b0-4e1d-bf5a-d0e1234abc56     → HTML (browser default)
/boards/9f4a1c2e-83b0-4e1d-bf5a-d0e1234abc56.md  → Markdown (forced)
/cards/a1b2c3d4-0000-0000-0000-000000000001.md    → Markdown (forced)
/docs/b2c3d4e5-0000-0000-0000-000000000002.md     → Markdown (forced)
Browsers always prefer text/html in their Accept headers, so the suffix is the only reliable way to get markdown in a browser tab or from a link. The suffix wins over any Accept value — it is checked first in the negotiation logic.
When writing agent prompts or tool instructions, give agents .md URLs rather than bare resource URLs. An agent that fetches /cards/{id}.md gets structured markdown with YAML frontmatter immediately — no Accept header configuration required, no risk of accidentally getting an HTML page. Because every link inside a markdown rendition also carries the .md suffix, an agent can follow links through an entire resource graph while staying in markdown the whole way.

YAML Frontmatter

Markdown renditions open with YAML frontmatter that carries the structured metadata an agent needs for round-trip operations:
---
id: "a1b2c3d4-0000-0000-0000-000000000001"
title: "Implement rate limiting"
version: 3
visibility: "private"
board: "9f4a1c2e-83b0-4e1d-bf5a-d0e1234abc56"
column: "c3d4e5f6-0000-0000-0000-000000000003"
doc: "d4e5f6a7-0000-0000-0000-000000000004"
linked_cards:
  - "/cards/e5f6a7b8-0000-0000-0000-000000000005.md"
linked_docs:
  - "/docs/f6a7b8c9-0000-0000-0000-000000000006.md"
---

Card body content follows here…
Object IDs (id, doc, board, column) are bare UUID strings in the frontmatter — suitable for API round-trips. Links in linked_cards and linked_docs carry the .md suffix so an agent following them stays in markdown. The version field is load-bearing. When an agent edits a document — whether a standalone doc or a card’s description — it must pass the version it read back as baseVersion in PUT /api/v1/docs/{id}. This is what enables the optimistic concurrency check. An agent that discards version may silently overwrite concurrent edits.

curl Examples

# Get a card as markdown (via Accept header)
curl -H 'Accept: text/markdown' https://hashboard.example.com/cards/<id>

# Same with the .md suffix — no Accept header needed
curl https://hashboard.example.com/cards/<id>.md

# Get a board as JSON
curl -H 'Accept: application/json' https://hashboard.example.com/boards/<id>

# Authenticated request (bearer token)
curl -H 'Authorization: Bearer hb_your_token_here' \
     https://hashboard.example.com/cards/<id>.md

# Get a standalone document and extract the version from frontmatter
curl -s https://hashboard.example.com/docs/<id>.md \
  | grep '^version:' | awk '{print $2}'

Unauthenticated Rendition Requests

Rendition consumers are treated as machines: an unauthenticated request for a rendition that requires authentication returns a plain 401 response, never a login redirect. This prevents an agent from silently receiving an HTML login page when it expected markdown, which would cause it to parse HTML as a document and produce nonsense edits.
# No credentials → 401 text/plain
HTTP/1.1 401 Unauthorized
Content-Type: text/plain

unauthorized
Anonymous requests for link-shared (link-read, link-write) or public resources work without credentials — they run as the Guest principal.

Implementation: Central Negotiation

Content negotiation is not handled per-route. It is intercepted in hooks.server.ts before SvelteKit’s router runs, backed by lib/server/renditions/:
  • renditions/negotiate.tswantedRendition() parses the Accept header and .md suffix; matchResource() matches the path to a resource type and ID.
  • renditions/markdown.ts — pure renderer functions; no I/O, no side effects.
This means adding a new resource type to Hashboard requires implementing all three renditions — HTML page, markdown renderer, and JSON shape. An HTML-only resource breaks the agent-native contract. The architecture document in CLAUDE.md flags this as a load-bearing invariant: every resource URL must be multimodal.
The MCP server’s read tools (get_board, get_card, get_doc) return the same markdown renditions as the .md URLs — they call renderRendition from the same renditions layer. The REST API, MCP tools, and URL renditions are three surfaces over a single implementation.

Build docs developers (and LLMs) love