BackmatterPricingDocs
Contents

Dev bar

The editor, chat, and publish, on the page you are browsing.

The dev bar sits on your site while you are in preview. The page is the preview. The bar opens the editor for the route you are on.

The bar is the frame. The editor, the agent, and publish are the Studio, mounted on this same site at /backmatter. Nothing crosses to another origin: the login is a cookie on your domain, and the panels are routes of your site.

Who sees it

Visitors see nothing. The layout ships a gate of a few hundred bytes that reads the URL and document.cookie and stops. No request leaves the page, and no editor code loads.

The gate opens for one of three things:

EntryWhen
?backmatter=1 on any URLA link an editor can keep. Works on a phone.
The marker cookie bm_ui=1Set when you enter preview. Lasts 30 days on this origin.
⌘⇧E (Ctrl+Shift+E)On a desktop, with no param and no marker.

Past the gate the page asks its own origin whether a site session exists. With one, the bar appears. Without one, the browser goes to the dashboard, which signs you in if needed, mints a ticket, and returns to the same page with the session and the marker set. Exit clears all three.

If you come back from the dashboard without a session, for instance because this site is not in the workspace's site URLs, the bar clears the marker and stays hidden instead of bouncing again.

On the site

Add the bar to the root layout of the site:

import { DevBar } from "@backmatter/next/devbar";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        <DevBar />
        {children}
      </body>
    </html>
  );
}

<DevBar /> takes studioPath when the Studio is mounted somewhere other than /backmatter, and previewEntryPath when the ticket route is not /api/backmatter/preview.

The site also needs the preview token, the preview route, the same-origin proxy, and the Studio route. backmatter init writes all of them. The workspace's site URL must be this site, or the dashboard refuses to return here.

What the bar does

The label on the left is the document for the route you are on (type/slug). Navigating the site changes it. The bar reads a marker the catch-all renders for that page, so a client navigation does not leave it stuck on the first document.

ControlWhat opens
Document nameThe document editor for this route
PublishThe commit flow for your working tree
AgentThe chat, focused on this document
ExitLeaves preview, clears the session and the marker, reloads the published page

⌘J and Ctrl+J open and close the agent. That still works while the editor, the chat, or publish has focus. Those panels send the shortcut back to the bar.

Editing is page-level. You open the editor for the route. The page around the panel is the preview, so the editor does not also frame the site.

The same editor

Each panel is a frame of the Studio on this site: /backmatter/…/content/…, /backmatter/embed/chat/…, /backmatter/embed/publish/….

The document panel is the document editor: the same fields, blocks, autosave, validation, save, and revert. Typing posts the open document to the page. The site re-renders that document with its own components. The save still goes to the working tree.

The agent is the chat from the dashboard. It follows the route. A write reloads the editor if it is open and refreshes the page.

Publish lists every file in your working tree. Conflicts block the commit until you keep yours or take theirs. Deploy commits those files, the same way the dashboard does. The count on the button is that list.

Because the Studio is part of the site's build, its version is the one in the site's package.json. The dashboard shows the version each site last reported under Settings → General.

On a client website

A client site is the same install as the test site. Set BACKMATTER_PREVIEW_TOKEN on the server that serves the site. Set the workspace site URL to the site's origin. Mount the Studio.

Editors open the site from the dashboard ("Open site" in the status bar, with a picker when the workspace has several sites), or they add ?backmatter=1 to any page. Their login lives on the dashboard; the site holds a 12-hour session cookie scoped to them, the workspace, the branch, and their tree. Logging out of the dashboard ends every site session.

Nothing on the client's domain is framed from another origin, so X-Frame-Options and third-party cookie settings do not matter. The dashboard's own split-view editor still frames the site; that path keeps working as before.