The Problem: Your BI Budget Is Burning
Tableau costs $900+/person/year, Power BI Pro costs $120+/person/year, and self-hosted BI tools like Metabase require complex deployment and maintenance. But here’s what most companies actually need:
Turn SQL query results into nice-looking charts, share them with the team or clients, and update them periodically.
That’s 80% of BI needs. Yet most tools are either too expensive, too heavy, or too painful to set up.
Is there a solution that’s zero software cost, one-command deployment, and requires nothing more than SQL knowledge?
Yes. Evidence.dev + DuckDB.
What Is Evidence.dev?
Evidence.dev (GitHub β 6.3k+) is an open-source BI as Code tool. Its core idea is remarkably simple:
Query data with SQL, write reports in Markdown, and generate a deployable static website.
It pairs perfectly with DuckDB:
| Feature | Evidence | Traditional BI |
|---|---|---|
| Data Source | DuckDB (native), CSV, Parquet, PostgreSQL, etc. | Requires data connector configuration |
| Query Language | Native SQL | Drag-and-drop or SQL-like |
| Report Authoring | Markdown + SQL code blocks | Drag-and-drop chart components |
| Version Control | Git (native support) | Not supported (or enterprise-only) |
| Deployment | npm run build β static site | Requires a server |
| Cost | Free | $10-$75/person/month |
| Learning Curve | 30 minutes (know SQL already) | 2-4 weeks |
Prerequisites
# 1. Install Node.js (v18+)
# 2. Create an Evidence project
npm create evidence@latest my-dashboard
cd my-dashboard
# 3. Install the DuckDB plugin
npm install @evidence-dev/duckdb
# 4. Start the development server
npm run dev
Note: Evidence automatically downloads the DuckDB embedded engine β no separate DuckDB installation needed.
Tutorial 1: Monthly Sales Dashboard
Project Structure
my-dashboard/
βββ sources/
β βββ duckdb/
β βββ connection.yaml # DuckDB data source config
βββ pages/
β βββ index.md # Home: monthly sales overview
β βββ customers.md # Customer analysis
β βββ products.md # Product analysis
βββ data/
βββ sales_sample.parquet # Sample data
Step 1: Generate Sample Data
Generate 100K rows of mock sales data in DuckDB:
-- Run this in DuckDB CLI to generate sample data
COPY (
SELECT
range::INTEGER + 1 AS order_id,
strftime(date '2025-01-01' + INTERVAL (range % 365) DAY, '%Y-%m-%d') AS order_date,
CASE WHEN range % 5 = 0 THEN 'Electronics'
WHEN range % 5 = 1 THEN 'Apparel'
WHEN range % 5 = 2 THEN 'Food & Beverage'
WHEN range % 5 = 3 THEN 'Home & Garden'
ELSE 'Books & Stationery' END AS category,
CASE WHEN range % 20 = 0 THEN 'Beijing Flagship'
WHEN range % 20 = 1 THEN 'Shanghai Store'
WHEN range % 20 = 2 THEN 'Guangzhou Store'
WHEN range % 20 = 3 THEN 'Shenzhen Store'
WHEN range % 20 = 4 THEN 'Hangzhou Store'
WHEN range % 20 = 5 THEN 'Chengdu Store'
WHEN range % 20 = 6 THEN 'Wuhan Store'
WHEN range % 20 = 7 THEN 'Nanjing Store'
WHEN range % 20 = 8 THEN 'Chongqing Store'
WHEN range % 20 = 9 THEN "Xi'an Store"
ELSE 'Online Channel' END AS store,
ROUND(50 + (range % 100) * 1.5 + (range % 30)::DOUBLE, 2) AS unit_price,
(range % 20) + 1 AS quantity,
ROUND((50 + (range % 100) * 1.5 + (range % 30)) * ((range % 20) + 1), 2) AS amount,
CASE WHEN range % 3 = 0 THEN 'New'
WHEN range % 3 = 1 THEN 'Returning'
ELSE 'VIP' END AS customer_type
FROM generate_series(0, 99999)
) TO 'data/sales_sample.parquet' (FORMAT PARQUET);
Step 2: Configure the DuckDB Data Source
Edit sources/duckdb/connection.yaml:
# sources/duckdb/connection.yaml
name: duckdb
type: duckdb
filename: my_dashboard.duckdb # DuckDB database file
options:
memory_limit: 2GB
threads: 4
Create initialization SQL sources/duckdb/init.sql:
-- sources/duckdb/init.sql
-- Load Parquet data into DuckDB
CREATE OR REPLACE VIEW sales AS
SELECT * FROM read_parquet('data/sales_sample.parquet');
-- Create monthly aggregation view
CREATE OR REPLACE VIEW monthly_sales AS
SELECT
strftime(order_date, '%Y-%m') AS month,
category,
store,
SUM(amount) AS revenue,
COUNT(*) AS order_count,
SUM(quantity) AS total_units,
ROUND(AVG(amount), 2) AS avg_order_value
FROM sales
GROUP BY month, category, store;
Step 3: Create the Home Page β Monthly Overview
Edit pages/index.md:
---
title: Monthly Sales Report
---
# π Monthly Sales Report
**Data Period:** January 2025 - December 2025
---
## π Monthly Revenue Trend
```sql monthly_revenue
SELECT
month,
SUM(revenue) AS total_revenue,
SUM(order_count) AS total_orders
FROM monthly_sales
GROUP BY month
ORDER BY month
π Key Metrics This Month
SELECT
SUM(revenue) AS revenue,
SUM(order_count) AS orders,
COUNT(DISTINCT store) AS active_stores,
ROUND(SUM(revenue) / SUM(order_count), 2) AS avg_order
FROM monthly_sales
WHERE month = (SELECT MAX(month) FROM monthly_sales)
πͺ Store Performance Ranking
SELECT
store,
SUM(revenue) AS total_revenue,
SUM(order_count) AS total_orders,
ROUND(AVG(avg_order_value), 2) AS avg_order_value,
ROUND(SUM(revenue) * 100.0 / SUM(SUM(revenue)) OVER(), 1) AS revenue_pct
FROM monthly_sales
GROUP BY store
ORDER BY total_revenue DESC
| Rank | Store | Revenue | Orders | Avg Order | Share |
|---|---|---|---|---|---|
| {#each store_ranking as s, i} | |||||
| {i+1} | {s.store} | ${s.total_revenue} | {s.total_orders} | ${s.avg_order_value} | {s.revenue_pct}% |
| {/each} |
π¦ Category Analysis
SELECT
month,
category,
SUM(revenue) AS revenue
FROM monthly_sales
GROUP BY month, category
ORDER BY month, category
### Step 4: Build and Deploy
```bash
# Build the static site
npm run build
# Preview locally
npm run preview
# Deploy to Vercel (one command)
npx vercel --prod
# Or deploy to Netlify
npx netlify deploy --prod
After building, you’ll get a complete static site in the build/ directory with:
- Interactive charts (hover for details, zoom, export as PNG)
- Responsive layout (mobile/tablet/desktop)
- Navigation and search
- Data download buttons
Tutorial 2: E-Commerce Operations Dashboard (Multi-Page)
A more complete dashboard with multi-page navigation, parameter filtering, and auto-refresh.
Page Structure
pages/
βββ index.md # Overview
βββ sales.md # Sales analysis
βββ inventory.md # Inventory analysis
βββ reports.md # Scheduled reports
Core code for parameterized sales analysis (pages/sales.md):
---
title: Sales Analysis
---
# π° Deep Sales Analysis
## Filters
```sql stores_list
SELECT DISTINCT store FROM sales ORDER BY store
SELECT
MIN(order_date) AS min_date,
MAX(order_date) AS max_date
FROM sales
Pareto Analysis (80/20 Rule)
WITH product_revenue AS (
SELECT
category,
SUM(amount) AS revenue
FROM sales
WHERE 1=1
AND store = '${inputs.selected_store.value}'
OR '${inputs.selected_store.value}' = '__all__'
GROUP BY category
),
cumulative AS (
SELECT
category,
revenue,
SUM(revenue) OVER (ORDER BY revenue DESC) AS running_total,
SUM(revenue) OVER () AS total_revenue
FROM product_revenue
)
SELECT
category,
revenue,
ROUND(revenue * 100.0 / total_revenue, 1) AS pct,
ROUND(running_total * 100.0 / total_revenue, 1) AS cumulative_pct
FROM cumulative
ORDER BY revenue DESC
Insight: Usually 20% of categories drive 80% of revenue. Use this to guide inventory and marketing decisions.
---
## Effect Comparison
| Factor | Tableau / Power BI | Evidence + DuckDB |
|--------|:------------------:|:------------------:|
| Software Cost | $6,000-60,000/year | **$0** |
| Setup Time | 2 days - 2 weeks | **10 minutes (`npm run build`)** |
| Version Control | β Not supported | β
Git-native |
| Collaboration | Platform sharing | **Markdown files + PR reviews** |
| Customization | Product-limited | **Full control (add HTML/CSS/JS)** |
| Data Refresh | Complex scheduling | **cron + git push** |
| Offline Access | β Needs internet | β
Pure static files, any browser |
| Learning Curve | 2-4 weeks | **30 minutes (know SQL already)** |
---
## π Scheduled Auto-Refresh
Set up zero-maintenance auto-refresh with cron:
```bash
# Refresh data and redeploy daily at 2 AM
0 2 * * * cd /path/to/my-dashboard && \
duckdb my_dashboard.duckdb < sources/duckdb/refresh.sql && \
npm run build && \
cd build && \
git add -A && \
git commit -m "daily data refresh $(date +%Y-%m-%d)" && \
git push origin gh-pages
If using Vercel/GitHub Pages auto-deploy, it’s even simpler:
# Just update data and push β auto-deploy handles the rest
0 2 * * * cd /path/to/my-dashboard && \
duckdb my_dashboard.duckdb < sources/duckdb/refresh.sql && \
git add -A && \
git commit -m "auto update $(date +%Y-%m-%d)" && \
git push origin main
π° Monetization Strategy
Target Clients
- Local SMBs: $0.5M-$5M monthly revenue, need data dashboards but won’t pay for Tableau
- E-commerce Sellers: Need aggregated multi-store dashboards (Shopify + Amazon + Etsy + own store)
- Multi-location Retailers: Need daily/weekly location performance reports
- Startups: Need investor-facing operational data dashboards
Pricing
| Service Type | Price Range | Description |
|---|---|---|
| One-time Setup | $300-$800 | Requirements gathering, data integration, dashboard design, deployment |
| Monthly Maintenance | $50-$150/month | Weekly/monthly data updates, metric adjustments, phone support |
| Annual Contract | $500-$1,500/year | Discounted annual rate with priority response and custom metrics |
Delivery Checklist
- Client provides data (CSV exports / read-only DB access / API tokens)
- Set up Evidence + DuckDB dashboard
- Deploy to client’s domain (or provide intranet access)
- Provide 30-minute training session
- Deliver source Git repository β client can modify independently
Sales Pitch
“Tableau costs $900+/person/year. For your 10-person team, that’s $9,000/year just for licenses. My solution costs zero in software β you just need someone who knows SQL to maintain it. And 80% of your reporting needs are trends, rankings, and breakdowns β Evidence handles all of them perfectly. Setup takes 10 minutes.”
π Expansion Ideas
- SaaS Embedding: Embed Evidence dashboards into your product as a premium feature
- Multi-tenant: Different clients get separate DuckDB databases; one Evidence project manages all
- Data Products: Generate industry-specific reports (e.g., “Monthly Restaurant Industry Insights”) and sell subscriptions
- Training: Create a video course teaching Evidence + DuckDB, sell for $99/license
- Data Integration: Help clients export data from SAP/Oracle/QuickBooks into DuckDB + Evidence, add $200-$500 per project
Summary
Evidence.dev + DuckDB = The definitive BI as Code stack.
| Learning Cost | Setup Speed | Software Cost | Maintainability |
|---|---|---|---|
| 30 minutes | 10 minutes | $0 | Very low (Git + cron) |
For 80% of enterprise BI needs β turning SQL query results into beautiful, interactive web dashboards β this solution is more than enough. For the remaining 20% (real-time streaming, granular access control, natural language queries), you can layer on additional tools as needed.
Build your first Evidence dashboard today, then sell it to your first client tomorrow.
All code tested with Evidence v41.0, DuckDB 1.5.2, and Node.js v22 Evidence docs: https://docs.evidence.dev DuckDB docs: https://duckdb.org/docs