0009. Server-rendered admin bar and a draft-safe page loader
- Status: Accepted
- Date: 2026-10-04
Context
Section titled “Context”Editors need to move easily between the public site and the dashboard, as with Drupal’s toolbar. StudioCMS 0.6 offers only a client-side “Quick Tools” corner menu (an avatar in the bottom-right corner, shown after the first mouse movement). Its “Edit” link goes to the content list rather than the current page, and its ~18 KB script ships to every visitor, logged in or not. There are no third-party StudioCMS plugins for this (the ecosystem is 8 official packages).
While investigating, we found that SDKCoreJs.GET.page.bySlug() does not filter
drafts, and the official @studiocms/blog route (which our playground route
copied) serves drafts to anyone who knows the URL.
Decision
Section titled “Decision”getPage(Astro)(@nascencestudio/tapestry/page) loads a page by slug and enforces visibility: drafts returnnull(→ 404) unless the viewer is an editor. It setsCache-Control: private, no-storefor editors andX-Robots-Tag: noindexfor drafts. The access rules are a pure function (pageAccess()) with unit tests.getViewer(Astro)resolves the session with StudioCMS’s ownUser.getUserData(), because StudioCMS only populates session locals for dashboard and API routes. It fails closed.<AdminBar>(@nascencestudio/tapestry/AdminBar.astro) is server-rendered, zero-JS, and emitted (markup and inline CSS) only for editors.- The playground disables StudioCMS’s corner menu (
features.injectQuickActionsMenu: false).
Alternatives considered
Section titled “Alternatives considered”- Client-side bar (like StudioCMS’s Quick Tools). Works with fully static caching, but ships JavaScript to every visitor and fires a session request from every browser. Rejected: conflicts with our zero-JS goal.
- Middleware that injects the bar into every HTML response. No layout change needed, but rewriting response bodies is fragile (streaming, non-HTML responses) and still needs page identity for “Edit page”. Might be offered later as an opt-in convenience.
- Patch StudioCMS’s Quick Tools. It’s injected from StudioCMS’s own source; there’s no extension point for menu items.
Consequences
Section titled “Consequences”- Site owners make two small changes (use
getPage, add<AdminBar>), both documented in admin-bar.md. - Responses rendered for editors can’t be shared-cached (correct, since they contain admin UI and possibly drafts). Anonymous responses are unchanged.
- Requests that carry a session cookie cost one session lookup.
- The inline
<style>needs CSP allowance for editors; a nonce option can follow. - Style isolation:
all: initialplus selectors anchored on#tapestry-adminbar. (Class-based selectors lost to a site rule like.site a, which turned the bar’s links purple. Found 2026-10-05 and covered by an e2e color check.) - The same
getPage()is the hook for the upcoming preview feature: a preview token will make it serve unsaved draft content to the editor who requested it.
Source: docs/decisions/0009-server-rendered-admin-bar.md (view on GitHub)