Apr 4, 2026 3.2 KB markdown

cdn

name: cdn
description: serve content from the edge — content-addressed URLs, format negotiation, shadow branch rendering, and caching

sublimated serves content through a global CDN backed by content-addressed storage (CAS). every blob is immutable and cached aggressively at the edge.

content-addressed storage

all content is stored by its BLAKE3 hash. same bytes = same hash = same URL forever. no cache invalidation needed — new content gets a new hash.

upload content:

PUT https://api.sublimated.com/v1/spaces/{slug}/content
Content-Type: application/octet-stream

{raw bytes}

returns: { contentHash: "blake3-af13...", sha256Hash: "...", sizeBytes: 1234 }

download by hash:

GET https://api.sublimated.com/v1/spaces/{slug}/content/{hash}

check existence:

POST https://api.sublimated.com/v1/cas/check
{ "hashes": ["blake3-af13...", "blake3-bc24..."] }

returns: { "have": [...], "missing": [...] }

URL routing and format negotiation

content is served at sublimated.com/{space}/{path} with format selection:

explicit extension:

  • /space/path/file.md — raw markdown (CAS blob)

  • /space/path/file.html — rendered HTML (from shadow branch)

  • /space/path/file.json — AST JSON (from shadow branch parser)

content negotiation (extensionless URLs):

  • Accept: text/html → rendered HTML

  • Accept: text/markdown → raw markdown

  • Accept: application/json → AST JSON

  • no Accept header → HTML (default)

folder vs file conflict (hello.md + hello/):

  • /hello → the file (rendered as HTML)

  • /hello/ (trailing slash) → folder index

shadow branch rendering

the CDN resolves formats from shadow branches, computed automatically on push:

  • raw content → CAS blob via item's contentHash

  • rendered HTML → refs/sbl/{branch}/html/{path}

  • AST JSON → refs/sbl/{branch}/markdown/{path}.ast.json

  • metadata → refs/sbl/{branch}/meta/{path}.json

shadow data is incremental — only changed items are reprocessed on push.

caching

CAS blobs are cached at the edge using Cloudflare Cache API:

  • cache key = content hash (immutable, never invalidated)

  • TTL: 24h+ (content never changes, TTL only controls eviction)

  • per-colo caching: fills naturally as users access content from each location

what is cached:

  • CAS blobs (API downloads and git clone)

  • materialized files (keyed by materializedHash)

  • git pack responses (keyed by ref + commit hash)

what is NOT cached:

  • mutable data (item listings, space metadata, refs)

  • user-specific data (access rules, sessions, tokens)

large file uploads

for files over 100MB, use presigned R2 upload:

POST https://api.sublimated.com/v1/spaces/{slug}/cas/presign

returns a presigned URL for direct R2 upload.

CDN URLs in feedback

every write operation includes CDN URLs in the response:

API response: _meta.links.cdn: ["https://sublimated.com/space/path/file"]

git push: sideband line with view URL

see also

  • shadow-branches — how derived data is stored as orphan git refs

  • data-api — content upload and download endpoints

  • transforms — shadow branches that power format rendering

  • git-workflow — how pushes trigger CDN content updates