Documentation
Add Dashu to your product
Install the packages into your own backend to add administrator-only, natural-language analytics. Your application remains responsible for identity, permissions, database credentials, and persistence.
Embedded SDK
The SDK turns a question into validated, read-only SQL and returns typed rows plus a declarative display plan. Database selection and AI provider selection are independent. PostgreSQL is the currently implemented database adapter.
1. Install the packages
This Next.js example uses PostgreSQL, OpenRouter, and the optional React components. Node 20 or newer is required on the backend.
npm install @rophpad/dashu-core @rophpad/dashu-database-postgres @rophpad/dashu-provider-openrouter @rophpad/dashu-next @rophpad/dashu-react# .env.local — backend only
DASHU_DATABASE_URL=postgresql://dashu_reader:password@host:5432/app
OPENROUTER_API_KEY=sk-or-...2. Configure Dashu on the server
Create one server-side instance. Use a dedicated PostgreSQL role with onlySELECT on approved views or tables.
// lib/dashu.ts
import { createDashu } from "@rophpad/dashu-core";
import { postgresAdapter } from "@rophpad/dashu-database-postgres";
import { openRouterProvider } from "@rophpad/dashu-provider-openrouter";
export const dashu = createDashu({
ai: openRouterProvider({
apiKey: process.env.OPENROUTER_API_KEY!,
model: "openai/gpt-4.1-mini",
}),
dataSources: {
analytics: postgresAdapter({
connectionString: process.env.DASHU_DATABASE_URL!,
schemas: ["analytics"],
}),
},
defaultDataSource: "analytics",
defaults: {
maxRows: 200,
statementTimeoutMs: 10_000,
exposeSql: false,
allowExport: false,
allowSaveDashboard: false,
denyTables: ["analytics.payment_tokens"],
denyColumns: ["analytics.customers.email"],
},
});3. Mount an authorized route
The browser sends only a question and bounded follow-up history. Resolve the actor, tenant, data source, and policy from your trusted server session—never from request JSON.
// app/api/dashu/ask/route.ts
import { dashuRoute } from "@rophpad/dashu-next";
import { dashu } from "@/lib/dashu";
import { requireCurrentUser } from "@/lib/auth";
export const runtime = "nodejs";
export const POST = dashuRoute(dashu, {
getActor: async (request) => {
const user = await requireCurrentUser(request);
if (!user.permissions.includes("dashu:ask")) return null;
return {
id: user.id,
tenantId: user.tenantId,
permissions: user.permissions,
};
},
// Select a configured name, not a connection string from the browser.
selectDataSource: ({ actor }) =>
actor.tenantId === "internal" ? "analytics" : undefined,
});Return null fromgetActor to deny access. Hiding the page in the frontend is not authorization.
4. Add the React UI
The hook owns fetch state, cancellation, retry, and up to six follow-up turns. The renderer uses only the validated result contract and never evaluates model-generated HTML.
// app/admin/analytics/AskData.tsx
"use client";
import { DashuComposer, DashuResult, useDashu } from "@rophpad/dashu-react";
export function AskData() {
const { ask, cancel, result, error, loading } = useDashu({
endpoint: "/api/dashu/ask",
keepHistory: true,
});
return (
<section>
<DashuComposer
onSubmit={(question) => void ask(question)}
onCancel={cancel}
loading={loading}
suggestions={["Revenue by month", "Top five products this quarter"]}
/>
{error && <p role="alert">{error.message}</p>}
{result && (
<DashuResult
result={result}
showSql={result.capabilities.showSql}
/>
)}
</section>
);
}You can replace individual renderers with your design system through thecomponents prop, or skip@rophpad/dashu-react and renderresult.display yourself.
Choose an AI provider
Swap only the ai value; the database adapter, route, and UI stay unchanged.
// Dashu Managed AI
import { managedProvider } from "@rophpad/dashu-provider-managed";
const ai = managedProvider({
cloudUrl: "https://dashu.dev",
credential: process.env.DASHU_INSTALLATION_CREDENTIAL!,
});
// OpenAI-compatible local or private endpoint
import { openAiCompatibleProvider } from "@rophpad/dashu-provider-openai-compatible";
const ai = openAiCompatibleProvider({
name: "Internal Ollama",
baseUrl: "http://ollama:11434/v1",
model: "qwen2.5-coder:7b",
});DASHU_INSTALLATION_CREDENTIAL in your backend environment — it is a bearer token and must never reach a browser. Creating a credential with the name of an existing one rotates it.Security checklist
- 1. Restrict database grants. Use a dedicated read-only identity with access only to approved schemas or views.
- 2. Authorize every request. Map your roles to permissions such as
dashu:ask,dashu:view-sql, anddashu:export. - 3. Enforce tenant isolation outside the model. Use separate databases, separate schemas, or PostgreSQL row-level security. Do not depend on generated
WHERE tenant_id = .... - 4. Keep secrets server-side. Never put database URLs, AI keys, or installation credentials in client components or
NEXT_PUBLIC_*variables. - 5. Persist deliberately. The SDK stores nothing. Use
onAnswerfor history you choose to retain andonEventfor metadata-only observability.
The PostgreSQL adapter also validates SQL, adds a hard row limit, and executes each statement inside a read-only transaction with a timeout. Those controls supplement—not replace—database permissions.
Package reference
| @rophpad/dashu-core | Request-scoped planning, policy, validation, execution, and result contracts. |
|---|---|
| @rophpad/dashu-database-postgres | PostgreSQL introspection, SQL guard, and read-only execution. |
| @rophpad/dashu-next | Authorized Next.js route handlers for questions, saved SQL, and schemas. |
| @rophpad/dashu-react | Question state, composer, tables, metrics, and charts for React 18+. |
| @rophpad/dashu-provider-openrouter | Use an OpenRouter API key owned by your organization. |
| @rophpad/dashu-provider-openai-compatible | Connect Ollama, vLLM, LocalAI, or another compatible endpoint. |
| @rophpad/dashu-provider-managed | Route planning through Dashu Managed AI with an installation credential. |
Advanced APIs include dashu.run()for re-validating and replaying saved SQL, dashu.schema()for an approved schema browser, and matchingdashuRunRoute anddashuSchemaRoute Next.js handlers.
Data and privacy
Database credentials and query result rows stay in your environment. With an external or managed AI provider, the question and filtered schema are sent for query planning.
The cloud site stores account, purchase, installation, quota, and usage metadata. It never needs your database connection string. Provider-specific retention and privacy terms still apply when you choose OpenRouter or another hosted endpoint.
Need managed AI or additional product capabilities? See plans or get in touch.