Express Example
Drizzle Cube Express Example
Section titled “Drizzle Cube Express Example”A minimal Express.js application demonstrating drizzle-cube integration with a simple analytics dashboard.
Features
Section titled “Features”- Express Backend: Simple server using drizzle-cube Express adapter
- React Frontend: Two-tab interface with dashboard and query builder
- PostgreSQL Database: Self-contained with Docker
- Sample Data: Employee and productivity analytics
Quick Start
Section titled “Quick Start”# Setup everything incl. database and seed datanpm run setup
# Start development servers (Express on :4001, React on :4000)npm run dev
Visit:
- Frontend Dashboard: http://localhost:4000
- Cube API: http://localhost:4001/cubejs-api/v1/meta
Architecture
Section titled “Architecture”Backend (server.js
)
Section titled “Backend (server.js)”- Express server with drizzle-cube adapter
- Simple security context (demo org/user)
- Cube API endpoints at
/cubejs-api/v1/*
Frontend (client/
)
Section titled “Frontend (client/)”- React app with Vite (port 4000)
- Vite proxy forwards
/cubejs-api/*
to backend (port 4001) - Two tabs: Dashboard view and Query Builder
- Uses
drizzle-cube/client
components with proper CSS imports - Includes react-grid-layout and recharts for dashboard functionality
Database
Section titled “Database”- PostgreSQL in Docker (port 54922)
- Sample employee, department, and productivity data
- Drizzle ORM for type-safe queries
Available Scripts
Section titled “Available Scripts”npm run dev # Start both server and clientnpm run dev:server # Server only (port 4001)npm run dev:client # Client only (port 4000)npm run build # Build for productionnpm start # Run production build
# Databasenpm run setup # Full setup (Docker + migrate + seed)npm run docker:up # Start PostgreSQLnpm run docker:down # Stop PostgreSQLnpm run db:migrate # Run migrationsnpm run db:seed # Seed sample data
Dashboard
Section titled “Dashboard”The example includes an editable 4-chart dashboard:
- Employees by Department (Bar Chart)
- Productivity Trend (Line Chart)
- Team Happiness Distribution (Pie Chart)
- Productivity by Department (Bar Chart)
Dashboard Editing
Section titled “Dashboard Editing”- Click “Edit Dashboard” to enable edit mode
- Drag charts to rearrange layout
- Resize charts using corner handles
- Edit individual chart settings
- Changes are automatically saved to localStorage
- Click “Reset” to restore default configuration
Note: This example uses localStorage for simplicity. In a production application, you would typically:
- Save dashboard configurations to your database
- Implement user-specific dashboard storage
- Add sharing and versioning capabilities
- Use proper authentication to control edit permissions
Query Builder
Section titled “Query Builder”Interactive query builder for:
- Selecting measures and dimensions
- Adding time dimensions with granularity
- Applying filters
- Live query execution
API Examples
Section titled “API Examples”# Get cube metadatacurl http://localhost:4001/cubejs-api/v1/meta
# Execute a querycurl -X POST http://localhost:4001/cubejs-api/v1/load \ -H "Content-Type: application/json" \ -d '{ "measures": ["Employees.count"], "dimensions": ["Departments.name"], "cubes": ["Employees", "Departments"] }'
Customization
Section titled “Customization”- Add Charts: Modify
client/src/dashboard-config.ts
for default dashboard - Add Cubes: Update
cubes.ts
and register in server - Styling: Edit Tailwind classes in React components or extend drizzle-cube CSS
- Security: Implement real authentication in
extractSecurityContext
- API Proxy: Modify
client/vite.config.ts
proxy settings if needed - Dashboard Persistence: Replace localStorage with database storage for production use
Production Dashboard Storage
Section titled “Production Dashboard Storage”For a real application, implement dashboard persistence like the Hono example:
// Add to your schemaexport const dashboards = pgTable('dashboards', { id: integer('id').primaryKey().generatedAlwaysAsIdentity(), name: text('name').notNull(), config: jsonb('config').notNull(), userId: integer('user_id').notNull(), organisationId: integer('organisation_id').notNull(), createdAt: timestamp('created_at').defaultNow()})
// Replace localStorage with API callsconst saveDashboard = async (config) => { await fetch('/api/dashboards', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ config }) })}
Differences from Hono Example
Section titled “Differences from Hono Example”This Express example is simplified yet functional:
- No Cloudflare Worker support - Node.js only
- localStorage persistence - For demo purposes (vs database storage in Hono)
- Fixed demo security context - No real authentication
- Minimal UI - Just 2 tabs (vs full navigation in Hono)
- No routing - Single page application
- Local-only dashboard customization - Changes not shared between users
Why localStorage vs Database?
Section titled “Why localStorage vs Database?”- Demo Purpose: Easy to test dashboard editing without backend complexity
- Development: Quick iteration on dashboard layouts during development
- Learning: Focus on drizzle-cube features without database setup
- Production: See customization section above for proper database persistence
Perfect for getting started, understanding core concepts, and experimenting with dashboard layouts before implementing production persistence!