Getting started
This guide takes you from nothing to a working MarkUp toolbar embedded in your app. It targets the @ceros/markup-sdk/ui entry point, which renders the full commenting UI.
Prerequisites
- A MarkUp workspace where you are an owner or admin (required to create an SDK installation).
- The page or app you want to collect feedback on.
1. Create an SDK installation
In the MarkUp web app, create an SDK installation for your workspace. You’ll come away with two values:
- a
publicKey— a browser-safe identifier for your installation, and - a
markupId— the MarkUp the SDK loads comments for.
While creating it you also set allowed origins — the origin(s) where your app runs. These are required if you want to use Sign in with MarkUp; if you authenticate with your own backend (onTokenNeeded) or call server-to-server, you can choose Allow all origins instead.
Follow Create an SDK installation for the full walkthrough, then come back here. Keep both values handy.
2. Install the package
The SDK is published to the Ceros private registry (GitHub Packages). Point the @ceros scope at that registry by adding an .npmrc to your project (or your home directory):
@ceros:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}GITHUB_TOKEN must be a token with the read:packages scope that has access to the Ceros organization. Then install:
npm install @ceros/markup-sdk3. Initialize and render
Import from the /ui entry, initialize with your publicKey and markupId, and call render():
import {MarkUpSDK} from "@ceros/markup-sdk/ui";
const markup = MarkUpSDK.init({
publicKey: "<YOUR_PUBLIC_KEY>",
markupId: "<YOUR_MARKUP_ID>"
});
markup.render();MarkUp is a singleton: the lifecycle is init → render → destroy. Call destroy() before re-initializing — for example when a single-page app unmounts the view or during hot reload:
markup.destroy();4. Authenticate your users
The SDK needs a user session before it can load and post comments. You choose how that happens by whether you pass onTokenNeeded.
Option A — Sign in with MarkUp
Omit onTokenNeeded and the SDK handles sign-in itself. On render() it makes one silent single-sign-on attempt; if that fails, the toolbar shows a Sign in button that opens a MarkUp sign-in popup. The signed-in user must be a member of the MarkUp’s workspace.
const markup = MarkUpSDK.init({
publicKey: "<YOUR_PUBLIC_KEY>",
markupId: "<YOUR_MARKUP_ID>"
});
markup.render();Option B — Bring your own token
Provide onTokenNeeded to authenticate users with your own backend. The SDK calls it when it needs a token; your backend returns a short-lived JWT signed with your installation’s private key, and the SDK exchanges it for a MarkUp session.
const markup = MarkUpSDK.init({
publicKey: "<YOUR_PUBLIC_KEY>",
markupId: "<YOUR_MARKUP_ID>",
onTokenNeeded: async () => {
const res = await fetch("/api/markup-token");
const {token} = await res.json();
return token;
}
});
markup.render();See Authentication for the JWT claim reference, a backend signing example, and the full sign-in flow.
5. Verify it works
Reload your page. You should see the MarkUp toolbar anchored at the bottom of the viewport. Enter commenting mode (press C, or use the toolbar), click anywhere on the page to drop a pin, and post a comment. It appears as a thread in the MarkUp linked to your markupId.
If the toolbar doesn’t appear, enable debug logging to see what the SDK is doing:
const markup = MarkUpSDK.init({
publicKey: "<YOUR_PUBLIC_KEY>",
markupId: "<YOUR_MARKUP_ID>",
debug: true
});Next steps
- Configuration — customize the toolbar position, theme, and behavior.
- API reference — subscribe to events and call the SDK services.
- Authentication — production sign-in with your own backend.