Skip to content

Repository files navigation

Lumenboard

AI-native business intelligence: ask your warehouse questions in plain English, on governed metric definitions.

Live demo: https://www.freelancerportfoliohub.com/jameslee/projects/lumenboard/index.html

Preview

Overview

Lumenboard sits between a company's data warehouse and the people who make decisions with it. Every metric has one reviewed definition, an owner and a certification state in the semantic layer, and dashboards, scheduled reports and AI answers all compile their queries from it. Every AI answer shows the certified metrics it used, its filters and the generated SQL, so an analyst can check it in seconds.

This repository contains the marketing site (home, product tour, metrics catalog, pricing) and the live demo: a working executive dashboard for Harbor & Pine Supply Co., a sample outdoor retailer, driven by a deterministic simulation so every number reconciles across tiles, charts, tables and answers. The metric definitions, semantic layer, question planner and sample warehouse live in a Python service (semantic/) that the Next.js app calls over HTTP.

Features

  • Executive dashboard — four tabs (Overview, Revenue, Retention, Acquisition) and four date ranges (7D, 30D, 90D, 12M), each compared with the prior period; tab and range are kept in the URL.
  • Hand-rolled charts — SVG line/area charts with crosshair tooltips, stacked columns, ranked bars with prior-period ticks, a gross-to-net waterfall, a checkout funnel, sparklines and cohort heat maps. No chart library.
  • Semantic layer — governed metric definitions in YAML (semantic/definitions/), each with an owner, certification state, model, filters and dimensions. Definitions are validated when the service starts: every column, join, dimension and time grain a metric names must exist, and ratio metrics may not reference each other in a cycle. A compiler turns metric + dimension + filter requests into SQL, expanding ratio metrics into their component aggregates with safe division.
  • Ask Lumenboard — POST /v1/ask plans a question on certified metrics with a deterministic, rule-based parser (metric synonyms, dimensions, filters, time windows, grain, comparisons and rankings), compiles the plan through the semantic layer, runs it on the sample warehouse and returns a chart spec, a written explanation and the SQL. Questions the metrics can't answer get a hint, not a guess. An LLM planner can be plugged in; its plans are validated against the same definitions and fall back to the rules.
  • Sample warehouse — a DuckDB database seeded from the deterministic simulation (orders, order lines, products, sessions, media spend, shipments, inventory), so generated SQL runs as written and revenue reconciles with the dashboard by day, channel and category.
  • Accessible, responsive — keyboard tabs, ARIA state on every control, tables and cohort grids that scroll inside their cards, and a layout that holds from 390px up.

Tech stack

Web app (repository root)

  • Next.js 15 (App Router) and React 19, TypeScript (strict)
  • Server components and server actions read the semantic service over HTTP (API_URL)
  • Plain CSS (app/globals.css) with design tokens as custom properties

Semantic service (semantic/)

Getting started

Start the semantic service (it seeds an in-memory warehouse on first start, about a second):

cd semantic
uv sync
uv run uvicorn lumenboard.api.app:app --reload --port 8000

Then the web app, in a second terminal from the repository root:

cp .env.example .env.local   # API_URL=http://localhost:8000
pnpm install
pnpm dev

Open http://localhost:3000 for the site and http://localhost:3000/demo for the dashboard. The API's interactive docs are at http://localhost:8000/docs.

Try the Ask API directly:

curl -s localhost:8000/v1/ask \
  -H 'content-type: application/json' \
  -d '{"question":"Which channels grew fastest this quarter?"}' | jq '.answer.sql'

curl -s localhost:8000/v1/ask \
  -H 'content-type: application/json' \
  -d '{"question":"top 3 categories by revenue last quarter excluding footwear"}' | jq '.answer.narrative'

Or compile and run a metric query without a question:

curl -s localhost:8000/v1/query \
  -H 'content-type: application/json' \
  -d '{"metrics":["aov"],"dimensions":["channel"],"timeRange":{"start":"2026-09-01","end":"2026-09-24"}}'

Testing

cd semantic
uv run pytest            # semantic layer, planner, warehouse reconciliation, API contract
pnpm typecheck && pnpm lint   # web app, from the repository root

Configuration

Variable Where Default Description
API_URL web app http://localhost:8000 Base URL of the semantic service
PORT service 8000 Port the container listens on
WAREHOUSE_PATH service :memory: DuckDB file for the sample warehouse (seeded if missing)
DEFINITIONS_DIR service semantic/definitions Metric, model and governance YAML
CORS_ORIGINS service none Comma-separated origins allowed to call the API from a browser
PLANNER service rules rules, or llm to plan with the command in LLM_COMMAND

semantic/Dockerfile builds the service with the warehouse seeded at build time and listens on $PORT; on Railway, point a service at the semantic/ directory and set the web app's API_URL to its URL.

Project structure

app/
  (marketing)/          home, product tour, metrics catalog and pricing pages
  demo/                 live dashboard
  actions.ts            server actions: load a dashboard panel, ask a question
  globals.css
components/
  ask/                  Ask panel, answer card, SQL block
  charts/               AreaChart, BarChart, HBarList, Waterfall, Funnel, Sparkline, lineage, tooltip
  dashboard/            DashboardShell, Sidebar, Tabs, RangePicker, KpiTile, DataTable, CohortGrid, panels/
  marketing/            page sections (hero, feature splits, catalog, pricing, FAQ)
  site/                 header, footer, logo
  ui/                   icons, buttons, tags, cards
lib/
  api.ts                typed client for the semantic service
  charts.ts             scales, ticks and chart geometry
  data/                 site copy (home, product tour, navigation)
types/                  shared types, including the service's response shapes
semantic/
  definitions/          metrics (one YAML file per metric), models, owners, governance and lineage
  src/lumenboard/
    semantic/           definition models, registry and validation, SQL compiler, YAML view, catalog
    planner/            rule-based question parser, time phrases, pluggable LLM planner
    ask/                curated investigations and warehouse-backed answers
    dashboard/          ranges, buckets and per-tab view models
    domain/             sample-workspace simulation, calendar, formatting, reference data
    warehouse/          DuckDB seed and read-only executor
    content/            pricing plans
    api/                FastAPI app and routes
  tests/
  Dockerfile
public/                 favicon and variable font

Scripts

Script Description
pnpm dev Start the web app with Turbopack
pnpm build Production build
pnpm start Serve the production build
pnpm lint Lint with the Next.js ESLint config
pnpm typecheck Type-check with tsc --noEmit
pnpm format Format with Prettier
uv run uvicorn lumenboard.api.app:app Serve the semantic service (semantic/)
uv run pytest Run the service tests (semantic/)
uv run lumenboard-seed data/wh.duckdb Seed a warehouse file (semantic/)