Embed in your app
The snippet adds Marca's floating bar to any page. If you'd rather review feel like part of your own product, use @marca/embed: Marca's feedback panel renders wherever you mount it, in your colours and font, reviewers are signed in by your app's own session, and there's no floating bar.
It uses the same element picker, area picker, composer and on-page pins as the snippet.
Install
npm install @marca/embed
Or load it straight from Marca without a bundler:
<script type="module">
import { createMarca } from 'https://marca.dev/snippet/embed.js';
</script>
Embed signs reviewers in through Sign-in from your app, so set that up first: see Sign-in from your app for the token endpoint your server needs. Add your app's origin under the project's allowed origins.
Use it
import { createMarca } from '@marca/embed';
const marca = createMarca({
endpoint: 'https://marca.dev',
project: 'proj_…',
identity: () => fetch('/marca-token').then((r) => r.text()),
theme: { accent: '#5b5bd6', radius: 8, font: 'inherit' },
});
// The panel: this page's open feedback, plus Add / Mark an area / pins.
marca.mount(document.querySelector('#review-sidebar')!);
// Or trigger the picker from your own UI.
document.querySelector('#feedback-button')!.addEventListener('click', () => marca.pick());
marca.on('task:created', (task) => toast(`Filed ${task.id}`));
API
| Call | Does |
|---|---|
createMarca(options) | Create the instance (one per page). Signs in through identity. |
marca.ready | Resolves once the first sign-in attempt has finished. |
marca.mount(el, { title?, currentPageOnly? }) | Render the feedback panel into el. Returns an unmount function. |
marca.pick({ area? }) | Let the reviewer pick an element (or drag an area) and file a task or comment. Resolves to { kind, id }, or null if they cancel. |
marca.showNotes(visible) | Show or hide existing feedback pinned on the page. |
marca.refresh() | Reload the panel. |
marca.identify(identity) | Swap the identity provider — call it when the signed-in user changes. Until it settles, session() is null and the panel, pins and actions wait. A provider that returns '' signs the reviewer out and takes the pins down. |
marca.linkAccount() | Let the reviewer link this identity to their own Marca account. |
marca.session() | { email, name } or null. |
marca.on(event, callback) | Subscribe; returns an unsubscribe function. |
marca.destroy() | Remove panels, pins and listeners. |
Options: endpoint, project, identity (a token string, or a function returning a fresh one), theme (accent, radius, font), and features.notes to show pins on load.
Events: ready, session, task:created, comment:created, item:select (a panel item was clicked — open it in your own UI), error.
Theming
theme sets three CSS custom properties on the page, which the panel, pickers and composer use. You can also set them in your own CSS:
:root {
--marca-accent: #5b5bd6;
--marca-radius: 8px;
--marca-font: inherit;
}
The panel otherwise inherits your text colour and size, so it sits on light and dark backgrounds alike.
Good to know
- Sign-in comes from your app. Embed never shows Marca's own login. Someone your app can't vouch for (or who an admin hasn't approved yet) sees a short explanation in the panel instead of the tools.
- Reviewer access only. Like every sign-in from your app, reviewers can comment and create tasks on this project; they can't edit tasks or reach the dashboard.
- Not included yet: the snippet's console/network log capture, and framework-specific wrappers (React, Vue). The vanilla API works in any framework — mount into a ref'd element and call
destroy()on unmount.