React 19 + TypeScript + Vite (rolldown-vite@7.2.2) + SWC
A demo internal tool for an AI API startup to track customer usage, monitor costs, and manage billing.
- Node: >=22.12.0
- Package Manager: pnpm >=8.0.0 (required)
- Install:
pnpm install - Dev:
major app start
CRITICAL: All resource access MUST go through auto-generated clients from @major-tech/resource-client.
Import and use the auto-generated clients from /src/clients/:
import { demoDbClient } from './clients';
const result = await demoDbClient.invoke(
'SELECT * FROM customers WHERE plan_tier = $1',
['enterprise'],
'fetch-enterprise-customers'
);
if (result.ok) {
console.log(result.result.rows);
}customers- Customer informationmodels- AI models available via APIapi_keys- Customer API keysusage_events- Individual API call eventsinvoices- Generated invoices
daily_usage_summary- Pre-aggregated daily usage per customer/modelcustomer_overview- Customer summary with total usagemodel_usage_stats- Model popularity and revenue
- Database credentials are READ-ONLY
- All mutations (invoices, alerts) are simulated in the frontend
- Data contains last 90 days of usage events
shadcn/ui: Use exclusively for all UI components.
Install new components:
pnpm dlx shadcn@latest add [component-name]Already installed: button, card, badge, input, select, popover, calendar, dropdown-menu, dialog, table, skeleton, separator, tooltip, command, scroll-area, switch, checkbox
src/
├── actions/ # All database queries (REQUIRED for DB access)
│ ├── kpi.actions.ts
│ ├── chart.actions.ts
│ ├── table.actions.ts
│ └── filter.actions.ts
├── components/
│ ├── ui/ # shadcn/ui components (auto-generated)
│ └── dashboard/ # Dashboard components
│ ├── charts/ # Recharts visualizations
│ ├── filters/ # Filter bar components
│ ├── table/ # TanStack Table implementation
│ └── actions/ # Simulated action modals
├── hooks/ # Custom React hooks
├── lib/ # Utilities, formatters, constants
├── providers/ # React context providers
└── types/ # TypeScript type definitions
| Library | Purpose |
|---|---|
@tanstack/react-query |
Data fetching & caching |
@tanstack/react-table |
Headless table with pagination |
recharts |
Charts (Area, Pie, Bar, Line) |
date-fns |
Date formatting & manipulation |
lucide-react |
Icons |
zod |
Schema validation |
pnpm install
major app startpnpm lint- Create query function in
/src/actions/:
// src/actions/my-feature.actions.ts
import { demoDbClient } from '@/clients';
export async function fetchMyData(param: string) {
const sql = `SELECT * FROM my_table WHERE column = $1`;
const result = await demoDbClient.invoke(sql, [param], 'fetch-my-data');
if (!result.ok) {
throw new Error(result.error.message);
}
return result.result.rows;
}- Use with TanStack Query in components:
const { data, isLoading } = useQuery({
queryKey: ['my-data', param],
queryFn: () => fetchMyData(param),
});- Install from shadcn:
pnpm dlx shadcn@latest add [component]- Import from
@/components/ui/[component]
Use Recharts components. See existing examples in /src/components/dashboard/charts/:
UsageOverTimeChart.tsx- Stacked area chartRevenueByModelChart.tsx- Pie/donut chartTopCustomersChart.tsx- Horizontal bar chartSuccessRateSparkline.tsx- Mini line chart
Filters sync to URL for shareable links. Use useFilterState hook:
const { filters, setDateRange, setPlanTiers } = useFilterState();Since the database is read-only, these actions are simulated:
- Generate Invoice - Creates fake invoice in local state
- Send Alert - Shows success toast (no actual email)
- Flag for Review - Toggles local flag state
- Export CSV - Real functionality (client-side generation)
All simulated actions show "Demo Mode" indicators.
- Add query to
src/actions/kpi.actions.ts - Add card to
src/components/dashboard/KpiSection.tsx
- Create chart component in
src/components/dashboard/charts/ - Add query to
src/actions/chart.actions.ts - Export from
src/components/dashboard/charts/index.ts - Add to dashboard layout in
src/App.tsx
- Create filter component in
src/components/dashboard/filters/ - Add state to
src/hooks/useFilterState.ts - Add to
FilterBar.tsx
- Edit
src/components/dashboard/table/UsageTableColumns.tsx - Add column definition with cell renderer
- Create modal in
src/components/dashboard/actions/ - Add state management to
src/providers/DemoStateProvider.tsx - Wire up in
src/App.tsx
All database rows are typed in /src/types/database.ts. Extend these types when adding new queries.
- Table uses server-side pagination (50 rows/page)
- Charts aggregate data server-side via SQL
- TanStack Query caches results (5 min stale time)
- Filters debounce text inputs (300ms)