How to Build Embedded Analytics with Cube Core on Next.js in 2025
How to Build Embedded Analytics with Cube Core on Next.js in 2025
Embedded analytics has become essential for SaaS applications, but building one from scratch involves complex data modeling, query optimization, and caching logic. Cube Core—an open-source semantic layer—abstracts this complexity and lets you define metrics once, then use them everywhere. This guide walks you through integrating Cube Core with a Next.js application.
Why Cube Core Works Well with Next.js
Cube Core provides REST, GraphQL, and SQL APIs, making it ideal for Next.js applications. Instead of writing complex SQL queries directly in your application, you define your business logic once in Cube's YAML data models, then query it through standardized APIs. This separation of concerns means your Next.js frontend stays clean and your data layer stays consistent across all clients.
The built-in relational caching engine delivers sub-second latency—critical for responsive dashboards. For teams building embedded analytics, this eliminates the performance bottlenecks that plague custom solutions.
Prerequisites
Before starting, ensure you have:
- Docker installed on your development machine
- Node.js 18+ and npm or yarn
- A basic Next.js project (or create one with
npx create-next-app@latest) - Access to a SQL data source (PostgreSQL, Snowflake, BigQuery, or Databricks)
Step 1: Spin Up Cube Core with Docker
The fastest way to get Cube Core running locally is through Docker. Create a new directory for your Cube project:
mkdir my-analytics-cube && cd my-analytics-cube
Then start the Cube Core container:
docker run -p 4000:4000 \
-p 15432:15432 \
-v ${PWD}:/cube/conf \
-e CUBEJS_DEV_MODE=true \
cubejs/cube
This command:
- Exposes port 4000 for the Cube Core API
- Mounts your current directory for configuration files
- Enables development mode for hot-reloading
Once running, navigate to http://localhost:4000 in your browser. Cube's interface will guide you through connecting a data source.
Step 2: Connect Your Data Source
Cube Core supports all major SQL databases. During the setup wizard, you'll be prompted to select your data source type. For this example, we'll use PostgreSQL:
CUBEJS_DB_TYPE=postgres
CUBEJS_DB_HOST=your-postgres-host
CUBEJS_DB_PORT=5432
CUBEJS_DB_NAME=your_database
CUBEJS_DB_USER=postgres_user
CUBEJS_DB_PASS=postgres_password
Add these environment variables to a .env.local file in your Cube project directory, then restart the container.
Step 3: Define Your First Data Model
Cube uses YAML files to define your semantic layer. These live in /cube/conf/model/cubes/. Create a file called orders.yml:
views:
- name: orders
sql: SELECT * FROM public.orders
dimensions:
- name: id
sql: id
type: number
primary_key: true
- name: status
sql: status
type: string
- name: created_at
sql: created_at
type: time
measures:
- name: count
type: count
- name: total_amount
sql: amount
type: sum
This defines:
- Dimensions: Categorical attributes (status, created_at) for filtering and grouping
- Measures: Aggregated metrics (count, total_amount) for analysis
Once saved, Cube will automatically detect and hot-reload the model.
Step 4: Query Cube Core from Next.js
Now create a Next.js API route to query Cube Core. Create pages/api/analytics/orders.ts:
import type { NextApiRequest, NextApiResponse } = from 'next';
type ResponseData = {
data?: Array<Record<string, any>>;
error?: string;
};
export default async function handler(
req: NextApiRequest,
res: NextApiResponse<ResponseData>
) {
try {
const response = await fetch('http://localhost:4000/cubejs-api/v1/load', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: {
measures: ['Orders.count', 'Orders.total_amount'],
dimensions: ['Orders.status'],
timeDimensions: [
{
dimension: 'Orders.created_at',
granularity: 'month',
},
],
},
}),
});
const analyticsData = await response.json();
res.status(200).json({ data: analyticsData.data });
} catch (error) {
res.status(500).json({ error: 'Failed to fetch analytics' });
}
}
Step 5: Display Data in a React Component
Create a component to visualize the analytics:
'use client';
import { useEffect, useState } from 'react';
export default function OrdersAnalytics() {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('/api/analytics/orders')
.then((res) => res.json())
.then((result) => {
setData(result.data || []);
setLoading(false);
})
.catch((err) => {
console.error('Analytics fetch failed:', err);
setLoading(false);
});
}, []);
if (loading) return <p>Loading analytics...</p>;
return (
<div>
<h2>Order Analytics</h2>
<table>
<thead>
<tr>
<th>Status</th>
<th>Order Count</th>
<th>Total Revenue</th>
</tr>
</thead>
<tbody>
{data.map((row, i) => (
<tr key={i}>
<td>{row['Orders.status']}</td>
<td>{row['Orders.count']}</td>
<td>${row['Orders.total_amount']}</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
Common Setup Challenges
| Issue | Solution |
|-------|----------|
| Connection refused to Cube Core | Verify Docker container is running: docker ps |
| CORS errors from Next.js | Query through your API route (as shown above), not directly from browser |
| Data models not loading | Check YAML syntax and restart container after file changes |
| Slow query performance | Review caching settings and ensure indexes exist on your data source |
Production Deployment Considerations
For production, avoid running Cube in development mode. Deploy using:
- Docker: Push to registry and orchestrate with Kubernetes or Docker Swarm
- Managed Cube Cloud: Use Cube's managed platform (affiliated service) for zero-ops deployment
- Self-hosted VPS: Deploy on DigitalOcean, Linode, or AWS EC2 with production-grade monitoring
Set CUBEJS_DEV_MODE=false and configure proper authentication with JWT tokens.
Next Steps
- Explore Cube's pre-aggregations for even faster queries
- Integrate with visualization libraries like Recharts or Chart.js
- Add role-based access control (RBAC) for multi-tenant analytics
- Connect additional data sources for a unified semantic layer
Cube Core transforms how you build analytics—from maintenance-heavy custom queries to a reusable, API-first data layer. With Next.js as your frontend framework, you've got a modern stack ready to power sophisticated embedded analytics.
Recommended Tools
- DigitalOceanCloud hosting built for developers — $200 free credit for new users
- VercelDeploy frontend apps instantly with zero config