Semaphor
Data Apps

Setup

Install the SDK, configure tokens and the provider, and debug Data Apps locally.

This page covers the details behind the Quickstart: package entry points, tokens, provider options, and DevTools.

Install

Add the package to an existing React 19 app (Vite, Next.js, or any React setup):

npm install react-semaphor

The SDK has three entry points:

Import pathUse it for
react-semaphor/data-app-sdkThe provider, semaphor.* builders, hooks, DevTools, and result types.
react-semaphor/data-app-sdk/adaptersConverting SDK query specs into analytics intents, for custom executors and tests.
react-semaphor/data-app-sdk/validationChecking query specs locally, for example in unit tests or CI.

Most apps only import from react-semaphor/data-app-sdk.

Tokens

The SDK authenticates with a project token. Mint it on your server with the Token API and send only the resulting accessToken to the browser.

server-side
const response = await fetch('https://semaphor.cloud/api/v1/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    type: 'project',
    projectId: process.env.SEMAPHOR_PROJECT_ID,
    projectSecret: process.env.SEMAPHOR_PROJECT_SECRET,
    tenantId: 'tenant_acme',
    endUserEmail: 'maria@acme.com',
    tokenExpiry: 3600, // seconds
  }),
});

const { accessToken } = await response.json();

The token decides what every query can see. Semaphor applies its tenant, end user, and security policies on the server for each request, exactly as it does for embedded dashboards. See Token Integration for actor fields, security parameters, and domain access.

Keep secrets server-side

Do not ship project secrets, dashboard secrets, or long-lived tokens in browser code.

Refreshing the token

Project tokens expire. Mint a new one before expiry and pass it to the provider's token prop. The provider picks up the new value on the next render, and later queries use it.

Provider

Every SDK hook must run under SemaphorDataAppProvider.

'use client'; // Next.js App Router only

import { SemaphorDataAppProvider } from 'react-semaphor/data-app-sdk';

export function DataAppRoot({
  token,
  children,
}: {
  token: string;
  children: React.ReactNode;
}) {
  return (
    <SemaphorDataAppProvider token={token}>
      {children}
    </SemaphorDataAppProvider>
  );
}

In Next.js, the provider and every component that calls an SDK hook are client components. Mint the token in a server component or route handler and pass it down as a prop.

PropRequiredMeaning
tokenYesThe project accessToken from your server.
apiBaseUrlNoSemaphor API URL. Defaults to the URL encoded in the token.
debugNoTurns on query tracing for DevTools. Keep it off in production.
executorNoCustom query executor, usually for tests.

API base URL

Semaphor Cloud tokens carry the API URL, so you usually omit apiBaseUrl. For self-hosted Semaphor or local development against your own instance, pass it explicitly:

<SemaphorDataAppProvider token={token} apiBaseUrl="http://localhost:3000/api">
  <App />
</SemaphorDataAppProvider>

The SDK sends queries to POST /api/v1/data-app/execute on that host.

DevTools

SemaphorDevtools is a floating panel that lists every query on the page with its kind, source, fields, inputs, pagination, execution status, and diagnostics. Enable it with the provider's debug prop:

import {
  SemaphorDataAppProvider,
  SemaphorDevtools,
} from 'react-semaphor/data-app-sdk';

const enableDevtools = import.meta.env.DEV; // Next.js: process.env.NODE_ENV !== 'production'

export function Root({ token }: { token: string }) {
  return (
    <SemaphorDataAppProvider token={token} debug={enableDevtools}>
      <App />
      <SemaphorDevtools
        initialIsOpen={false}
        buttonPosition="bottom-right"
        panelPosition="right"
      />
    </SemaphorDataAppProvider>
  );
}

DevTools render nothing while debug is off. To label which component owns a query, add a source hint:

const result = useSemaphorQuery(revenueBySegment, {
  debug: {
    sourceHint: {
      file: 'src/views/RevenueBySegment.tsx',
      component: 'RevenueBySegment',
    },
  },
});

Styling

The SDK is headless. It returns query state and typed results, and you render them with your own components. If your app uses shadcn/ui or another design system, use its cards, tables, and selects directly with SDK results.

Suggested File Structure

Keep query definitions separate from UI so you can see which query drives each visual:

src/
  semaphor/
    sources.ts      # semaphor.source.* and semaphor.field.*
    queries.ts      # semaphor.metric, records, matrix, analysis
    inputs.ts       # semaphor.filter, semaphor.control, option queries
  components/
    filters/
      CampaignFilter.tsx
      DateRangeFilter.tsx
    insights/
      RevenueKpi.tsx
      RevenueByCampaign.tsx
      OrdersTable.tsx
  App.tsx

Local Development Checklist

  • Confirm the token can access the target project and semantic domain.
  • Keep query specs source-bearing. Include source on every field that comes from a semantic dataset.
  • Prefer semantic metric, records, matrix, and analysis queries before SQL.
  • Add loading, empty, and error states to every visual.
  • Use server-side pagination for large tables.
  • Test with the same token scope your users will have.
  • Check executionResult and relationship diagnostics when a query returns partial data or fails.

On this page