deepspotscreen-sdk
v0.0.3
Published
Deepspot Embedded Analytics SDK — embed dashboards and reports in any website
Readme
Deepspot Embedded Analytics SDK
Embed Deepspot dashboards and reports into any website or framework — React, Next.js, Vue, Angular, Svelte, or plain HTML — with a single import or script tag.
Why Deepspot SDK?
| Feature | Details |
|---|---|
| No iframe | Renders directly in your page DOM — full CSS control |
| Self-contained | ApexCharts, html2canvas, jsPDF all bundled in |
| Lazy loading | Only the active tab's SQL queries execute |
| Row-level security | Pass a userId to scope data per end-user |
| React & Vue | Drop-in components with full TypeScript types |
| Next.js ready | SSR-safe, works with App Router and Pages Router |
| CDN friendly | Single UMD file — works with a <script> tag |
Table of Contents
- Installation
- Quick Start
- API Reference
- Embed Levels
- Supported Component Types
- Environment Variables
- Security
- Building from Source
- Troubleshooting
- License
Installation
# npm
npm install deepspotscreen-sdk
# pnpm
pnpm add deepspotscreen-sdk
# yarn
yarn add deepspotscreen-sdkPeer dependencies — React and Vue are optional peer deps. Install only what your project uses.
Quick Start
React / Next.js (App Router)
'use client' // required for Next.js App Router
import { DeepspotDashboard } from 'deepspotscreen-sdk/react'
export default function AnalyticsPage() {
return (
<DeepspotDashboard
apiKey="sk_live_b74c55..."
baseUrl="https://api.deepspot.ai"
dashboardId="dashboard_123"
embedLevel="dashboard"
userId="user_456"
theme="light"
height="600px"
onReady={() => console.log('Dashboard loaded')}
onFilterChange={(filters) => console.log('Filters changed:', filters)}
onError={(err) => console.error('Embed error:', err)}
/>
)
}Next.js (Pages Router)
import dynamic from 'next/dynamic'
// SSR must be disabled — the SDK uses browser APIs
const DeepspotDashboard = dynamic(
() => import('deepspotscreen-sdk/react').then(m => m.DeepspotDashboard),
{ ssr: false }
)
export default function Page() {
return (
<DeepspotDashboard
apiKey={process.env.NEXT_PUBLIC_DEEPSPOT_API_KEY!}
baseUrl={process.env.NEXT_PUBLIC_DEEPSPOT_BASE_URL!}
dashboardId={process.env.NEXT_PUBLIC_DEEPSPOT_DASHBOARD_ID!}
embedLevel="dashboard"
userId="user_456"
height="600px"
/>
)
}Vue 3 / Nuxt
<script setup lang="ts">
import { DeepspotDashboard } from 'deepspotscreen-sdk/vue'
</script>
<template>
<DeepspotDashboard
api-key="sk_live_b74c55..."
base-url="https://api.deepspot.ai"
dashboard-id="dashboard_123"
embed-level="dashboard"
:user-id="currentUser.id"
theme="light"
height="600px"
@ready="onLoaded"
@filter-change="onFiltersChanged"
@error="onError"
/>
</template>Plain HTML (CDN)
<!-- Load once in <head> — pinned to the version you tested with -->
<script src="https://unpkg.com/[email protected]/dist/deepspot-sdk.js"></script>
<!-- Place the element where the dashboard should appear -->
<deepspot-dashboard
dashboard-id="dashboard_123"
api-key="sk_live_b74c55..."
base-url="https://api.deepspot.ai"
user-id="user_456"
embed-level="dashboard"
theme="light"
height="600px"
></deepspot-dashboard>Angular / Svelte / Vanilla JS
import { DeepspotSDK } from 'deepspotscreen-sdk'
const sdk = new DeepspotSDK({
apiKey: 'sk_live_b74c55...',
baseUrl: 'https://api.deepspot.ai',
})
const dash = await sdk.embedDashboard({
dashboardId: 'dashboard_123',
container: document.getElementById('analytics')!,
userId: currentUser.id,
theme: 'light',
height: '600px',
})API Reference
React Component Props
<DeepspotDashboard>
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
| apiKey | string | ✅ | — | sk_live_... key from Embed & Share page |
| baseUrl | string | ✅ | — | Your Deepspot backend URL |
| dashboardId | string | ✅ | — | Dashboard ID from Deepspot |
| embedLevel | string | | "dashboard" | "dashboard" / "page" / "tab" / "report" |
| userId | string | | "" | End-user ID for row-level security |
| tenantId | string | | — | Tenant ID for multi-tenant apps |
| pageId | string | | first page | Starting page ID |
| tabId | string | | first tab | Starting tab ID |
| theme | string | | "light" | "light" or "dark" |
| height | string | | "600px" | CSS height value (e.g. "800px", "100vh") |
| hideFilters | boolean | | false | Hide the filter bar |
| hideExport | boolean | | false | Hide export buttons |
| filters | object | | {} | Initial filter values |
| className | string | | — | CSS class for the wrapper div |
| style | CSSProperties | | — | Inline styles for the wrapper div |
| loadingNode | ReactElement | | built-in spinner | Custom loading indicator |
| onReady | () => void | | — | Fires when dashboard finishes loading |
| onFilterChange | (filters: object) => void | | — | Fires when user changes a filter |
| onTabSwitch | (pageId: string, tabId: string) => void | | — | Fires when user switches tab |
| onError | (message: string) => void | | — | Fires on any load error |
<DeepspotReport> (Single Component)
Same as <DeepspotDashboard> but instead of embedLevel / pageId / tabId, pass:
| Prop | Type | Required | Description |
|---|---|---|---|
| componentId | string | ✅ | ID of the specific chart / table / KPI to embed |
Vue Component Props
Same props as React but in kebab-case (dashboard-id, api-key, base-url, etc.).
Events emitted via v-on / @:
| Event | Payload | Description |
|---|---|---|
| @ready | — | Dashboard loaded successfully |
| @filter-change | filters: object | User changed a filter |
| @tab-switch | { pageId, tabId } | User switched tab |
| @error | message: string | Load error occurred |
HTML Web Component Attributes
<deepspot-dashboard>
| Attribute | Required | Default | Description |
|---|---|---|---|
| dashboard-id | ✅ | — | Dashboard ID |
| api-key | ✅ | — | sk_live_... key |
| base-url | ✅ | — | Backend URL |
| user-id | | "" | End-user ID |
| embed-level | | "dashboard" | "dashboard" / "page" / "tab" / "report" |
| page-id | | first page | Starting page |
| tab-id | | first tab | Starting tab |
| theme | | "light" | "light" or "dark" |
| height | | "600px" | CSS height |
| hide-filters | | "false" | Set to "true" to hide filter bar |
| hide-export | | "false" | Set to "true" to hide export buttons |
<deepspot-report>
| Attribute | Required | Description |
|---|---|---|
| dashboard-id | ✅ | Dashboard that owns this component |
| component-id | ✅ | ID of the specific component to embed |
| api-key | ✅ | API key |
| base-url | ✅ | Backend URL |
| user-id | | End-user ID |
| theme | | "light" or "dark" |
| height | | CSS height |
JavaScript API (Programmatic Control)
import { DeepspotSDK } from 'deepspotscreen-sdk'
const sdk = new DeepspotSDK({
apiKey: 'sk_live_b74c55...',
baseUrl: 'https://api.deepspot.ai',
})
// Embed a full dashboard — returns an EmbedInstance
const dash = await sdk.embedDashboard({
dashboardId: 'dashboard_123',
container: '#analytics-section', // CSS selector or HTMLElement ref
userId: currentUser.id,
theme: 'dark',
filters: { region: 'US' },
onReady: () => console.log('ready'),
onFilterChange: (f) => console.log(f),
})
// Embed a single chart / KPI card
const report = await sdk.embedReport({
dashboardId: 'dashboard_123',
componentId: 'comp_revenue_chart',
container: '#revenue-widget',
userId: currentUser.id,
})
// ── EmbedInstance methods ──────────────────────────────────────────────────
dash.setFilter('region', 'EU') // apply one filter → re-fetches
dash.setFilters({ region: 'EU', year: '2024' }) // apply multiple at once
dash.goToPage('page_2') // navigate to a page
dash.goToTab('page_2', 'tab_q1') // navigate to a specific tab
dash.refresh() // force re-fetch current tab
dash.exportPDF() // download dashboard as PDF
dash.destroy() // remove from DOM and clean upEmbed Levels
| Level | What renders | Navigation shown |
|---|---|---|
| "report" | 1 chart / table / KPI card | None |
| "tab" | All components on 1 tab | None |
| "page" | All tabs on 1 page | Tab switcher |
| "dashboard" | Full dashboard, all pages | Page nav + Tab switcher |
All levels lazy-load — other tabs only execute SQL when the user clicks them.
Supported Component Types
| Type | Rendered as |
|---|---|
| bar | Bar chart (ApexCharts) |
| line | Line chart (ApexCharts) |
| area | Area chart (ApexCharts) |
| pie | Pie chart (ApexCharts) |
| donut | Donut chart (ApexCharts) |
| table | Paginated HTML data table |
| number-card | KPI / metric card |
| filter | Dropdown / date-range / multi-select filter |
| text | Static text block |
Environment Variables (Next.js)
Store your configuration in .env.local — never commit this file.
# .env.local
NEXT_PUBLIC_DEEPSPOT_API_KEY=sk_live_b74c55...
NEXT_PUBLIC_DEEPSPOT_BASE_URL=https://api.deepspot.ai
NEXT_PUBLIC_DEEPSPOT_DASHBOARD_ID=dashboard_123
NEXT_PUBLIC_DEEPSPOT_EMBED_LEVEL=dashboard
NEXT_PUBLIC_DEEPSPOT_THEME=light
NEXT_PUBLIC_DEEPSPOT_HEIGHT=600pxFor production, rotate your
apiKeyregularly and prefer the server-side token exchange pattern.
Security
Auth Flow
Your website
│ POST /embed-token { apiKey, dashboardId, userId }
▼
Deepspot Backend ──→ short-lived JWT (1-hour TTL)
│
│ GET /embed/:id/render { x-embed-token: <JWT> }
▼
SQL executes server-side → pre-computed rows returned
(No SQL, no DB credentials ever reach the browser)Production Best Practice
Avoid exposing your apiKey in public HTML. Exchange it for a short-lived token on your backend:
// YOUR backend endpoint — e.g. POST /api/embed-token
const response = await fetch(`${DEEPSPOT_URL}/dashboard-builder/embed-token`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-deepspot-api-key': process.env.DEEPSPOT_API_KEY, // server-side only!
},
body: JSON.stringify({ dashboardId, embedType: 'dashboard', userId }),
})
const { data: { token } } = await response.json()
// Return token to your frontend — expires in 1 hourBuilding from Source
Prerequisites
- Node.js >= 18
- npm / pnpm / yarn
git clone https://github.com/your-org/deepspot-sdk.git
cd deepspot-sdk
# Install dependencies
npm install
# Build main SDK bundle (UMD + ESM)
npm run build:sdk
# Build React + Vue framework wrappers
npm run build:frameworks
# Build everything in one command
npm run build
# Watch mode — rebuilds on every file change
npm run dev
# TypeScript type-check (no output)
npm run typecheckBuild Output
dist/
├── deepspot-sdk.js ← UMD (CDN / <script> tag / CommonJS require)
├── deepspot-sdk.esm.js ← ESM (bundler / import)
├── index.d.ts ← TypeScript declarations (single rolled-up file)
├── react/
│ ├── index.mjs ← ESM React wrapper
│ ├── index.cjs ← CJS React wrapper
│ └── index.d.ts
└── vue/
├── index.mjs ← ESM Vue wrapper
├── index.cjs ← CJS Vue wrapper
└── index.d.tsTroubleshooting
Dashboard renders with a transparent / unstyled background
The SDK inlines embed.css at build time. If you're building from source, ensure the build completed without errors — the styles are only present in dist/.
ReferenceError: __DS_EMBED_CSS__ is not defined
This means the framework wrapper was built without the define block from vite.frameworks.config.ts. Both config files must include the define: { __DS_EMBED_CSS__ } block.
Next.js App Router: "document is not defined"
Add 'use client' at the top of any file that imports from deepspotscreen-sdk/react. The SDK uses browser APIs and cannot run on the server.
Next.js Pages Router: hydration errors
Use dynamic(..., { ssr: false }) as shown in the Pages Router example.
TypeScript: cannot find module deepspotscreen-sdk/react
Ensure moduleResolution in your tsconfig.json is set to "bundler", "node16", or "nodenext" — these modes support the exports field in package.json.
Get Your API Key
- Open the Deepspot Dashboard Builder
- Navigate to Publish → Embed & Share
- Click Generate Key
- Copy the
sk_live_...key — it is scoped to that specific dashboard
Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feat/my-feature - Make your changes in
src/ - Run
npm run typecheckto verify TypeScript - Run
npm run buildto verify the build succeeds - Open a pull request
