@reportr/react
v0.1.1
Published
React SDK for embedding Reportr dashboards. Provides <ReportrDashboard>, hooks, filter bar primitives, and server-side RLS token signing.
Maintainers
Readme
@reportr/react
React SDK for embedding Reportr dashboards in your app. Ships <ReportrDashboard>, a Next.js server component for zero-ceremony RLS, filter primitives, hooks, and a server entry for signing RLS-scoped publication tokens.
Install
pnpm add @reportr/react react react-dom
# or: npm install @reportr/react react react-domPeer dependencies: React 18 or 19. Works with Next.js (App Router and Pages), Vite, Remix, and plain SPAs.
Two entries
The package exposes two entry points so server-only code stays out of client bundles:
| Import | Use it from | Purpose |
|---------------------------------|---------------------|------------------------------------------------------------|
| @reportr/react | Client components | Components, hooks, context. Carries a "use client" banner. |
| @reportr/react/server | Server components / route handlers | ReportrDashboardServer and mintRlsToken(). Imports server-only — bundling it into a client module will fail loudly. |
Quick start
Next.js App Router (recommended)
The simplest integration: drop ReportrDashboardServer into a server component. It wraps the provider + dashboard for you and uses a Next.js server action as the RLS-token callback, so the JWT is minted server-side and refreshed transparently when it expires mid-session.
// app/page.tsx
import { ReportrDashboardServer } from "@reportr/react/server";
// Required: prevents Next.js from caching one user's RLS token for all
// visitors. Without this, every visitor will see the first user's data.
export const dynamic = "force-dynamic";
export default function Page() {
return (
<ReportrDashboardServer
baseUrl={process.env.REPORTR_API_URL!}
apiKey={process.env.REPORTR_API_KEY!}
rlsSecret={process.env.REPORTR_RLS_SECRET!}
claims={{ storeIds: currentUser.storeIds }}
sub={currentUser.email}
slug="quarterly-revenue"
/>
);
}rlsSecret + claims are only needed when the publication was published with RLS required. For non-RLS publications, omit both — the provider just signs requests with the API key.
Plain React (any framework)
If you're not on Next.js App Router, wire the provider yourself:
"use client";
import { ReportrProvider, ReportrDashboard } from "@reportr/react";
export function MyEmbed() {
return (
<ReportrProvider
baseUrl="https://api.reportr.example.com"
apiKey={process.env.NEXT_PUBLIC_REPORTR_API_KEY!}
>
<ReportrDashboard id="quarterly-revenue" />
</ReportrProvider>
);
}For RLS-required publications, mint a token on your server (see "Server-side RLS token signing" below) and pass it via rlsToken on the provider.
<ReportrDashboard> props
| Prop | Type | Notes |
|---|---|---|
| id (required) | string | Publication slug |
| height | string \| number | Container height (defaults to 400 only in loading/error states) |
| filters | Filter[] | External filters merged with the dashboard's filter bar |
| theme | Partial<GlobalTheme> | Theme overrides applied on top of the published snapshot |
| onLoad | () => void | Fired once the publication is fetched |
| onError | (error: Error) => void | Fired on fetch failure |
| onFilterChange | (filters: Filter[]) => void | Fired when in-dashboard filters change |
| className | string | Class on the root wrapper |
| apiKey | string | Per-component override of the provider's apiKey |
RLS tokens
Reportr publications can be RLS-scoped — each viewer gets a JWT carrying claims your row-level-security rules consume. The token must be signed on the server using the publication's rlsSecret (returned once at publish time; store it in an env var).
With <ReportrDashboardServer> (Next.js)
You don't write any token plumbing — pass rlsSecret, claims, and (optionally) sub to <ReportrDashboardServer> and you're done. Tokens default to a 15-minute lifetime and refresh automatically on the SDK's 401-retry path.
Without server components — mint manually
// app/api/reportr-token/route.ts (Next.js App Router)
import { mintRlsToken } from "@reportr/react/server";
export async function GET() {
const token = mintRlsToken(
process.env.REPORTR_RLS_SECRET!,
{ organizationId: "acme", role: "viewer" },
{ sub: "[email protected]", expiresIn: "15m" }
);
return Response.json({ token });
}Then pass the token to the provider — as a static string, or (recommended) as a callback that returns a fresh one. When rlsToken is a callback and the server returns 401, the SDK re-invokes it once and retries the request, giving you transparent mid-session refresh:
<ReportrProvider
baseUrl={...}
apiKey={...}
rlsToken={async () => {
const r = await fetch("/api/reportr-token");
const { token } = await r.json();
return token;
}}
>
<ReportrDashboard id="..." />
</ReportrProvider>mintRlsToken(secret, claims, opts?) options: sub?: string (JWT subject), expiresIn?: string | number (default 15m).
What's in the bundle
All public exports from the client entry:
- Components —
ReportrDashboard,FilterBar,FilterBarShell,FilterBarTop,SelectFilterRow,MultiSelectFilterRow,DateRangeFilterRow,NumberRangeFilterRow - Hooks —
useDashboard,useChartData,useFilters,useFilterOptions,useFilterBarState - Context —
ReportrProvider,useReportrClient - Client factory —
createReportrClient,ReportrApiError(only needed if making API calls outside a provider) - Filter helpers —
buildDefaultFilterValues,filterValueToQueryFilters,isFirstOptionSentinel,FIRST_OPTION_SENTINEL - Formatters —
formatNumber(re-exported from@reportr/charts)
From the server entry:
ReportrDashboardServermintRlsToken(secret, claims, opts?)
Full docs
See the main repo for the API reference, dashboard publishing workflow, and RLS configuration: https://github.com/KnowItAllAus/reportr
License
MIT © KnowItAllAus
