Semaphor
Data Apps

Setup

Install the SDK, configure tokens, and run Data Apps locally.

Install

For a new app, use the bootstrapper:

npx create-semaphor-app@latest my-data-app
cd my-data-app
npm run dev

Optional scaffold-time choice:

npx create-semaphor-app@latest my-data-app --shadcn-preset <preset-id>

<preset-id> is a shadcn preset from shadcn create, not a Semaphor package or component registry.

The starter includes Semaphor components and samples by default, so there is no separate Semaphor component install step for new apps.

Use manual setup when you are adding Semaphor to an existing React app or you want to control the Vite/shadcn initialization yourself.

npm install react-semaphor

Use the Data App SDK subpath:

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

shadcn And Semaphor Components

If the app uses shadcn, initialize it with the customer's preset or style before adapting any component source.

npx shadcn@latest init --template vite

With a shadcn preset from shadcn create:

npx shadcn@latest init --preset <preset-id> --template vite

For new apps, create-semaphor-app already includes Semaphor source components for query state, filters, KPI cards, server tables, matrix tables, and sample dashboards. For existing apps, prefer your app's own UI components and copy or adapt starter source only when you need those reusable mechanics. These components do not replace react-semaphor/data-app-sdk.

Runtime Provider

Every query hook must run under SemaphorDataAppProvider.

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

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

If the app is running inside Semaphor's published Data App runtime, the provider can read the runtime token automatically. For local development, pass a token explicitly.

API Base URL

Hosted Semaphor uses the API URL encoded in the token. For local development or a self-hosted environment, pass apiBaseUrl.

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

Token Handling

Generate tokens on your server. The browser should receive only the scoped access token it needs to render the Data App.

server-side example
async function createDataAppToken() {
  const response = await fetch('https://semaphor.cloud/api/v1/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      dashboardId: process.env.SEMAPHOR_DASHBOARD_ID,
      dashboardSecret: process.env.SEMAPHOR_DASHBOARD_SECRET,
    }),
  });

  if (!response.ok) {
    throw new Error(`Token request failed: ${response.status}`);
  }

  return response.json();
}

Keep secrets server-side

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

Suggested File Structure

For small experiments, one file is fine. For real apps, keep query ownership visible.

src/
  data-app/
    sources.ts
    fields.ts
    queries.ts
    inputs.ts
  components/
    filters/
      CampaignFilter.tsx
      DateRangeFilter.tsx
    insights/
      RevenueKpi.tsx
      RevenueByCampaign.tsx
      OrdersTable.tsx
  App.tsx

This structure helps humans and agents answer: "Which visual owns which query?"

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 and error states to every visual.
  • Use server-side pagination for large tables.
  • Check executionResult and relationship diagnostics when a query returns partial data or fails.

On this page