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-semaphorThe SDK has three entry points:
| Import path | Use it for |
|---|---|
react-semaphor/data-app-sdk | The provider, semaphor.* builders, hooks, DevTools, and result types. |
react-semaphor/data-app-sdk/adapters | Converting SDK query specs into analytics intents, for custom executors and tests. |
react-semaphor/data-app-sdk/validation | Checking 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.
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.
| Prop | Required | Meaning |
|---|---|---|
token | Yes | The project accessToken from your server. |
apiBaseUrl | No | Semaphor API URL. Defaults to the URL encoded in the token. |
debug | No | Turns on query tracing for DevTools. Keep it off in production. |
executor | No | Custom 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.tsxLocal Development Checklist
- Confirm the token can access the target project and semantic domain.
- Keep query specs source-bearing. Include
sourceon every field that comes from a semantic dataset. - Prefer semantic
metric,records,matrix, andanalysisqueries 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
executionResultand relationship diagnostics when a query returns partial data or fails.