Overview
Build custom analytics UI in your own React app with governed Semaphor queries.
The Data App SDK lets you build your own analytics UI in React while Semaphor handles the data. Your components declare what they need, and Semaphor runs each query server-side through the same governed execution as your dashboards: semantic definitions, relationships, tenant scoping, and security policies all apply.
Use the SDK when a dashboard card is not enough: custom workflow screens, operational tables, branded KPI strips, or analytics woven into an existing page of your product.
What You Build
A Data App is your own React code that uses react-semaphor/data-app-sdk. You define:
- sources and fields: the semantic datasets and source-bearing measures, dimensions, dates, and ids you query;
- queries: KPI, records, matrix, analysis, input-options, or SQL fallback specs;
- inputs: filters, selections, and controls that users can change;
- views: your components that render the results.
Semaphor executes the query and returns typed results to your app.
import {
SemaphorDataAppProvider,
semaphor,
useSemaphorQuery,
} from 'react-semaphor/data-app-sdk';
const orders = semaphor.source.semantic({
domainId: 'commerce',
datasetName: 'fact_orders',
});
const revenue = semaphor.field.measure('revenue', {
source: orders,
aggregate: 'SUM',
});
function RevenueKpi() {
const result = useSemaphorQuery(
semaphor.metric({
id: 'revenue_kpi',
label: 'Revenue',
source: orders,
measures: [revenue],
primaryMeasure: revenue,
}),
);
if (result.isLoading) return <div>Loading revenue...</div>;
if (result.error) return <div>{result.error.message}</div>;
return <strong>{result.primaryValue}</strong>;
}
export function App({ token }: { token: string }) {
return (
<SemaphorDataAppProvider token={token}>
<RevenueKpi />
</SemaphorDataAppProvider>
);
}The token is a project token your server mints with the Token API. It decides which tenant, user, and security policies apply to every query.
Why This Is Different From Client-Side Analytics
Data Apps are not a "fetch every row and filter in the browser" pattern. Your app declares intent, and Semaphor executes that intent through governed server-side analytics.
This matters because production analytics often need:
- relationship-aware filters, such as a Campaign dropdown filtering an Orders fact table;
- joined labels, such as revenue by campaign name instead of campaign id;
- cascading filters, such as Region narrowing State;
- server-side pagination and sorting for large tables;
- diagnostics when a relationship is missing, ambiguous, or unsafe.
Start Here
Quickstart
Add a governed KPI to your existing React app.
Setup
Configure tokens, the provider, API URLs, and DevTools.
SDK Concepts
Learn how sources, fields, queries, inputs, rows, and columns fit together.
Relationship-Aware Filters And Joins
Learn how Semaphor resolves human-readable dimensions through modeled relationships.
Core Mental Model
Imagine a commerce company with this semantic model:
fact_orders
order_id
order_date
campaign_id
store_id
revenue
dim_campaign
campaign_id
campaign_name
channel
dim_store
store_id
store_name
state_id
dim_geo
region_id
region_name
state_id
state_namefact_orders stores revenue and ids. dim_campaign, dim_store, and dim_geo store human-readable labels. Semaphor's semantic model defines relationships such as:
fact_orders.campaign_id -> dim_campaign.campaign_id
fact_orders.store_id -> dim_store.store_id
dim_store.state_id -> dim_geo.state_idWith those relationships, a Data App can:
- show revenue from
fact_orders; - display campaign names from
dim_campaign; - filter revenue by campaign name;
- cascade Region and State options from
dim_geo; - apply Region and State filters to
fact_ordersthroughdim_store.
Your app authors the source and field refs. Semaphor proves and executes the relationships.