Shell for an analytics dashboard:
- React 19 + react-router-dom 7 (CRA)
- Power BI Embedded (service-principal, app-owns-data)
- Server-side env-var login (2 users)
- Vercel serverless
/api/*in prod, Express mirror (server.js) in local dev - Visual system ported from the Claude Design "AdventureWorks Executive Dashboard" mock — neutral surfaces, single indigo accent
The Power BI canvas + auth flow are wired. Visuals (D3) and filter wiring will be added in a later pass.
npm install
cp .env.example .env # fill in Azure + AUTH_USER* values
npm run server # terminal 1: Express embed/login proxy on :5000
npm run dev # terminal 2: React app on :3000CRA's proxy field forwards /api/* to localhost:5000.
All server-side. Never prefix with REACT_APP_* — that bakes secrets into the client bundle.
| Var | Purpose |
|---|---|
AZURE_CLIENT_ID |
Service principal app ID |
AZURE_CLIENT_SECRET |
Service principal secret (mark Sensitive in Vercel) |
AZURE_TENANT_ID |
Azure tenant |
AZURE_AUTHORITY_URL |
https://login.microsoftonline.com/ |
POWERBI_SCOPE |
https://analysis.windows.net/powerbi/api/.default |
POWERBI_WORKSPACE_ID |
Target workspace |
POWERBI_REPORT_ID |
Target report |
AUTH_USER1_EMAIL / AUTH_USER1_PASSWORD |
First demo user |
AUTH_USER2_EMAIL / AUTH_USER2_PASSWORD |
Second demo user |
PROXY_PORT |
Local Express port (default 5000) |
FRONTEND_URL |
CORS allow-list entry for local dev |
- Import the repo into Vercel.
- Add all env vars from
.env.examplein Settings → Environment Variables. MarkAZURE_CLIENT_SECRETandAUTH_USER*_PASSWORDas Sensitive. - Build command:
npm run build. Output:build/. vercel.jsonrewrites/api/*to the serverless functions inapi/and falls everything else through toindex.htmlfor client-side routing.
api/
embed-token.js MSAL service principal → PBI embed token
health.js
login.js Validates against AUTH_USER*_EMAIL/PASSWORD
public/
index.html
manifest.json
src/
App.js Router + AuthProvider + protected route
App.css CSS variables + ported design-system styles
index.js / index.css
context/AuthContext.js useAuth(), login(), localStorage hydration
pages/
LoginPage.js
DashboardPage.js Sidebar + TopBar + FilterRow + CanvasArea
components/
Sidebar.js Nav + user chip (from design mock)
TopBar.js Breadcrumb + page title (from design mock)
FilterRow.js Date / Region / Territory / Category / Rep chips
Icon.js Stroke icon set
CanvasArea.js PowerBIEmbed wrapper + token refresh
data/
salespeople.js Static rep list for the Rep chip
services/
powerbiService.js getEmbedConfig() — filter-mapping stub for later
server.js Local-dev Express mirror of /api
vercel.json
Calendar Year → Month drilldown. Display formats:
- All time →
All time - Year only →
CY 2025 - Year + Month →
Apr 2025
(No fiscal year, no quarter.)