DOCUMENTATION

Publishing & the Public Renderer

Last updated May 2026
Publishing
All plans

When you publish a document, BlnkSpace renders it through a server-side async React component called the Block Renderer. This page explains how publishing works end-to-end — from enabling a public URL to how each block type is rendered for visitors.

Publishing a document

Every document in BlnkSpace has a Published toggle. When turned on, the document becomes accessible at its public URL. When turned off, visitors see a 404 — the document and its content are never exposed.

Share button → Publish toggle
Flip the Published switch to make the document public. The URL appears immediately.
Unpublish
Flip the toggle back off at any time. The page returns a 404 for all visitors instantly.
Public URL
Shown in the Share panel. The URL is based on your subdomain (or custom domain) and the document slug.
Publishing is per-document. Sub-pages are only accessible if their parent site has a subdomain configured. Publishing the root document and its sub-pages does not require each sub-page to be individually toggled — they inherit publishability from the site.

How the renderer works

Published pages are rendered by an async React Server Component — no client-side JavaScript is required to display the content. The renderer receives the document's blocks, layout (navbar/footer), typography settings, and colors, then converts each block to its HTML equivalent server-side.

The rendering pipeline:

  • The middleware rewrites tenant hostnames (your subdomain or custom domain) to an internal /site-render route, passing the host and path as query params.
  • The site-render page resolves the document from the host/path combination, fetches the blocks and layout, then passes them to BlockRenderer.
  • BlockRenderer is a server component. It iterates all blocks, recursively resolving column children, section children, and toggle children, rendering each into React nodes.
  • The final HTML is sent to the browser. Most content requires zero JavaScript to display.

ISR caching

Published pages are cached using Next.js Incremental Static Regeneration (ISR) with a 60-second revalidation window. This means:

  • The first visit after a cache miss renders the page fresh from the database.
  • Subsequent visits within 60 seconds are served from the CDN cache — extremely fast.
  • After 60 seconds, the next request triggers a background revalidation. Visitors still see the cached version while the new one builds.
  • Content changes appear on the public page within ~60 seconds of saving in the editor.
The 60-second window is a trade-off between freshness and performance. If you need changes to appear immediately (e.g. correcting a typo on a live page), wait up to 60 seconds and then hard-refresh the public URL.

Typography on published pages

The document's typography tokens (font family, font size, line height, letter spacing) are applied to each block via a blockWrapStyle function. This function reads the document-level typography and merges it with any block-level overrides from the selection toolbar.

The cascade is:

  • Block-level override (set via selection toolbar) wins first.
  • Document typography (set via the Typography picker or a branding preset) applies if no block override is set and the value is non-default.
  • Hardcoded fallback (the renderer's own defaults) applies last.
Document-level typography values of 'normal' (for size/line height/letter spacing) and 'inter' or 'default' (for font family) are treated as "not set" by the renderer — they don't override the block's own defaults. Only non-default values cascade down.

Google Fonts on published pages

If the document uses a Google Font (for the body, navbar, or footer), the font stylesheet is injected server-side into the page HTML. No JavaScript is required — the <link> tag appears in the rendered HTML so the browser starts fetching the font immediately. Fonts are deduplicated: if the body and navbar share the same font, only one request is made.

Block rendering reference

The table below shows how each block type is handled in the public renderer. "SSR" means the block renders entirely server-side with no client JavaScript. "Client island" means the block requires a client component for interactivity but falls back gracefully if JS is slow to load.

Block typeRender modeNotes
Paragraph, HeadingsSSRTipTap HTML rendered server-side. Typography tokens applied via wrapStyle.
List, Numbered, TodoSSRBullet/number markers rendered as inline spans. Typography tokens applied.
Quote, CalloutSSRBorder and background from theme. Content via TipTap HTML.
DividerSSRHorizontal rule with configurable color.
ButtonSSRRendered as an anchor tag with inline styles.
ToggleClientExpand/collapse requires a client island. Content children are SSR.
Code BlockSSRRaw code in a <pre> tag. No syntax highlighting on published pages.
ImageClientDither and ASCII display modes require canvas — rendered as client islands. Default/clean modes are SSR.
EmbedClientiframe — client only.
Hero SectionClientBackground effects (Three.js, shaders) require client. Static hero variants are SSR.
SectionSSRBackground image, overlay, and child blocks all SSR.
CarouselClientSwipe/drag requires client. SSR fallback shows first slide.
Tab BarClientTab switching is client-side. Content of all tabs is SSR.
Infinite CarouselClientCSS animation set via JS on mount.
DatabaseSSRTable view rendered server-side. Row peek and editing are editor-only.
SpreadsheetSSRRendered as a static HTML table. No editing on published pages.
EquationSSRKaTeX renders to HTML server-side.
BibliographySSRReference list and inline citations rendered server-side.
3D SceneClientThree.js and Spline are dynamically imported (ssr: false). Shows loading placeholder until ready.
Product blocksClientCommerce blocks use PublicCommerceShell — one server fetch, shared across all commerce blocks on the page.
YouTube ShortsEditor onlyThis block does not render on published pages — it's a management/analysis tool.
Product CMSEditor onlyManagement interface only. Not rendered on published pages.

If a document has useNavbar or useFooter enabled, the site layout's navbar/footer configuration is rendered above and below the block content respectively. Both are SSR — no client JavaScript required for the navigation structure itself. Dropdown menus require a client island for the open/close interaction.

If no footer is configured, BlnkSpace renders a minimal attribution footer with a "Made with BlnkSpace" link.

Content width

The document's width setting controls how content blocks are constrained. Named widths map to Tailwind classes; custom pixel values use inline styles. Full-width blocks (Hero, Section, Carousel, Infinite Carousel) always span 100% of the viewport regardless of the document width setting.

SettingClass / value
narrowmax-w-2xl (672px)
widemax-w-4xl (896px)
fullw-full (no max-width)
custominline style: max-width: Npx