TotalBase
Settings

Share

Public links and signed embeds, to show a dashboard outside TotalBase.

In the admin: Dashboards › a Dashboard › Settings › Share

Share shows a published dashboard on another site, to visitors without a TotalBase account. Each way it's shown is an embed: a public link for data that may be public, or a signed embed for a portal that shows each visitor their own data. Acme's public Service status page uses a link; its customer portal uses a signed embed of the Customer portal dashboard.

Changes here apply at once, without publishing. Every embed shows the dashboard's published version: a publish updates them all, and a draft never shows.

Settings › Share of the Customer portal dashboard: a signed embed being designed, with its live preview.
Settings › Share of the Customer portal dashboard: a signed embed being designed, with its live preview.

Before you start

  • Allow embedding, the dashboard's switch at the top. Off, none of its embeds shows anything.
  • Sites that may embed, in Settings › Dashboards (Embedding): the exact origins allowed to frame an embed, such as https://portal.acme-field.example. Until there's one, no site can frame any embed; the preview here works anyway.
  • The embedding secret, in the same place, for signed embeds: the secret your portal's backend signs tokens with. It never reaches a browser.

Notices on the page say when the dashboard has unpublished changes and when no site may frame an embed yet.

Designing an embed

New embed opens the form beside a live preview: the real embed page, at Desktop, Tablet or Phone width, showing exactly what the form says.

Field
NameUp to 32 characters, unique in the dashboard: Website, Customer portal
KindPublic link or Signed (portal). Chosen once
ThemeAuto, Light or Dark
RefreshAs the dashboard, Off, or an interval
Show the title and descriptionthe dashboard's name and description above it
Transparent backgroundthe embedding page shows through
Allow downloadseach widget's ⋮ offers CSV, Excel and an image. Off by default
Show private filesimages the queries return that aren't public files, such as a technician's photo. Off by default: Image not available on this link
Variableseach published variable's mode and value (below)
Sites that may frame itsome of the instance's sites. Empty: all of them
ExpiresNever, In 30 days, In 90 days, In a year

Create link or Create signed embed saves it. Editing an embed keeps its link and its tokens working.

Allow downloads is a convenience, not a protection: whatever the queries return is already in the visitor's browser.

Variables

Each variable the published version has gets a mode. A value is written as in the App's address: a preset or 2026-01-01..2026-03-31 for a period, commas between several values.

Mode
EditableIn the bar: the visitor chooses. The value is where it starts. A new variable is Editable until you say otherwise
HiddenNot in the bar: bound to its value, or its default. Not a restriction: it says nothing the dashboard doesn't show
LockedFixed by the embed: the visitor can never change it. The embed's restriction

Only Locked restricts data. Use it with a query such as WHERE s.customer = $VAR.customer::uuid. A public link needs a value for each Locked variable. On a signed embed, a Locked variable left empty is given by the token, per visitor.

An embed has no viewer: $USER is unavailable, and a widget whose query uses it fails. A click runs only when it filters a variable the visitor may change, or opens a URL marked Also in embeds; the form lists the widgets whose click doesn't run there.

The link is the access: https://acme.example/admin/embed/tbe_…. Anyone who has it sees the dashboard. It sits in the embedding page's HTML and also opens outside a frame, where the page says Only available embedded: a deterrent, not security. The sites only decide who may frame it.

Use a public link only for data that may be public, such as orders completed this week and the average response time.

Signed (portal)

For private or per-visitor data. The URL to frame is https://acme.example/admin/embed/<embed id>#<token>. For each page view, your portal's backend signs a short-lived token naming the embed and the values that depend on the visitor. The token travels after #, so it's never sent to a server or logged.

The token is a JWT signed with HS256 and the embedding secret. Its payload:

{ "resource": { "embed": "6f1c2a4e-…" }, "params": { "customer": "b3e9…" }, "exp": 1767225600 }
  • resource.embed: the embed's id. The dashboard's id never appears.
  • params: a value for every Locked variable the embed leaves empty, and nothing else.
  • exp: required, in seconds, in the future and at most an hour away by default.

Any other algorithm, a wrong signature, an expired token or a wrong params is refused. Copy payload gives the shape for an embed. In Node, with no library:

import { createHmac } from 'node:crypto'

const part = (value) => Buffer.from(JSON.stringify(value)).toString('base64url')

export function customerPortalUrl(secret, embedId, customerId) {
  const header = part({ alg: 'HS256', typ: 'JWT' })
  const payload = part({
    resource: { embed: embedId },
    params: { customer: customerId },
    exp: Math.floor(Date.now() / 1000) + 10 * 60
  })
  const signature = createHmac('sha256', secret).update(`${header}.${payload}`).digest('base64url')
  return `https://acme.example/admin/embed/${embedId}#${header}.${payload}.${signature}`
}

Its embeds

The list shows each embed's name, kind, status (Active, Expired, Revoked, Needs update), when it was last used and when it expires, with:

  • Copy link (a public link) or Copy URL and Copy payload (a signed embed);
  • Copy iframe: the frame, with a listener that sizes it to the dashboard's height;
  • Edit;
  • Revoke: it stops at once, for good. A revoked embed can then be deleted.

Creating, changing, revoking and deleting an embed are recorded in the audit log.

Failing closed

Variables change between versions. If the published version no longer has a variable an embed locks, that embed stops showing anything (Needs update), rather than show the dashboard without its restriction. Before you publish, the editor's Publish lists the embeds it would stop. A variable an embed doesn't lock that's gone is simply gone.

Next steps