busi488energy/CLAUDE.md
2026-02-11 22:44:04 -05:00

7.8 KiB

Bonus Assignment 4 — Energy & AI Dashboard

This project builds a real-time interactive dashboard showing how AI datacenter buildout is driving regional electricity demand and energy prices across the US. Read SPEC.md in full before starting any work — it contains the business case, technical architecture, database schema, and implementation phases. Understanding why this dashboard exists (not just what it does) will make your code better.

Read the Spec

Before writing a single line of code, read SPEC.md cover to cover. Every agent on this project — orchestrator, builder, reviewer, tester — should understand:

  • The business case: AI datacenters are reshaping US energy markets. This isn't a toy dashboard — it's a tool for people making billion-dollar infrastructure decisions.
  • The user: Energy investors, utility analysts, datacenter site selectors. They need real-time visibility, not static reports.
  • The real-time candy: The ticker tape, pulsing markers, GPU cost calculator, grid stress gauges — these are what make the dashboard feel alive. They're not afterthoughts.

Code that understands its purpose is better code. A developer who knows why the GPU cost calculator exists will make better implementation decisions than one who's just following a component spec.

Code Standards

Type Safety is Non-Negotiable

This project is end-to-end type-safe. Every boundary is validated:

  • External APIs (EIA, FRED): Zod schemas validate every response. Never trust untyped JSON.
  • Database: Prisma generates types for standard CRUD. TypedSQL generates typed wrappers for PostGIS queries.
  • Server → Client: Server Actions and Server Components pass typed props. No any leaking across the boundary.
  • Serialization: Use superjson for all server-to-client data passing. React's default serialization silently converts Date objects to strings, Map to {}, Set to {}, etc. — but TypeScript still thinks they're the original type. This is a silent type lie. superjson preserves Date, BigInt, Map, Set, RegExp, undefined, and other types across the wire. Wrap Server Action returns and component props through superjson serialize/deserialize. This is especially critical for this project — almost every data point has a timestamp.
  • No any. No as unknown as X. No @ts-ignore. No // @ts-expect-error. If you can't type it, you don't understand it well enough yet.

Write Clean Code

  • Meaningful names. getRegionPriceHeatmap, not getData. datacenterMarkerPulseAnimation, not anim1.
  • Small functions. If a function does more than one thing, split it.
  • Co-locate related code. A component's types, helpers, and styles should live near the component.
  • No dead code. Don't comment things out "for later." Delete it. Git has history.
  • Handle errors at the boundaries. Zod parse failures, API timeouts, database connection errors — handle them where they occur, with meaningful messages. Don't let errors propagate silently.
  • Follow existing patterns. Before creating something new, check if there's already a pattern in the codebase for it. Consistency matters more than personal preference.

Styling

  • Dark theme only. Every component should look great on a dark background.
  • Tailwind 4 only. No inline styles. No CSS modules. Use Tailwind utility classes and shadcn/ui component variants.
  • shadcn/ui first. Before building a custom component, check if shadcn/ui has one. Use their chart components (Recharts wrappers) for all data visualization.
  • Responsive. Everything should work on desktop and tablet at minimum.

Timestamps & Timezones

  • Store everything in UTC. All TIMESTAMPTZ columns, all in-memory dates, all API responses — UTC.
  • Display in market-local time. ERCOT → Central, PJM → Eastern, CAISO → Pacific. Convert only at the render layer.
  • Use formatMarketTime(utcDate, regionCode) — a shared utility in src/lib/utils.ts for consistent display.

Performance

  • Server Components by default. Only use "use client" when you need interactivity (maps, charts, forms, animations).
  • Cache aggressively. Use Next.js 16's "use cache" directive for data that doesn't change every request.
  • Don't fetch in loops. Batch database queries. Use PostGIS spatial joins instead of N+1 queries.
  • Lazy load heavy components. Google Maps, Recharts — use next/dynamic with ssr: false where appropriate.

Testing

  • No unit tests. They devolve into testing constants and mocking everything. Useless.
  • Integration tests only. Test the real pipeline: API → Zod → Postgres → query → typed result. Against the real database.
  • E2E smoke tests. Every page renders, map loads, charts display data, no console errors.
  • The minimum bar for any task: bunx tsc --noEmit passes, bun run lint passes, the page renders with real data.

Tech Stack & Constraints

Concern Choice Notes
Package manager bun Not npm, not yarn, not pnpm. Always bun.
Python uv If any Python is needed, always use uv.
Framework Next.js 16 App Router. Turbopack. "use cache" directive.
Styling Tailwind CSS 4 CSS-first config.
Components shadcn/ui Latest, with tw-animate-css.
Maps @vis.gl/react-google-maps Google's recommended React library. Use AdvancedMarker.
Database PostgreSQL 18 + PostGIS 3.5 Docker Compose. Port 5433 (5432 is taken).
ORM Prisma 7.x with TypedSQL .sql files in prisma/sql/ for geo queries.
Charts Recharts via shadcn/ui chart components Consistent theming out of the box.
Serialization superjson Preserves Date, BigInt, Map, Set across server→client. Required for all Server Actions and temporal data.
Animations framer-motion For number transitions, pulse effects, etc.
Toasts sonner For price spike notifications.

Existing Files (Do NOT Overwrite)

These config files are already in the project root with the user's preferred settings:

  • .prettierrc.js — Prettier configuration
  • eslint.config.js — ESLint configuration
  • tsconfig.json — TypeScript configuration
  • .env — API keys (Google Maps key, Google Maps Map ID, EIA, FRED). Never log, commit, or expose these.

When scaffolding the Next.js project, you must integrate with these existing configs, not replace them. Install whatever dependencies they require.

Version Discipline

Use the latest stable versions of everything. There have been recent JS CVEs — do not pin to old versions out of habit. When installing a package, let bun resolve the latest. If a specific version is required for compatibility, document why.

Browser Automation

Use agent-browser for visual verification. Run agent-browser --help for all commands.

agent-browser connect 9222     # Connect to chromium
agent-browser open <url>       # Navigate to page
agent-browser snapshot -i      # Get interactive elements with refs
agent-browser click @e1        # Click element
agent-browser fill @e2 "text"  # Fill input

Always re-snapshot after page changes to get fresh element refs.

Project Structure

See SPEC.md for the full directory tree. Key landmarks:

  • prisma/schema.prisma — Database schema (Prisma + PostGIS)
  • prisma/sql/ — TypedSQL query files for geospatial operations
  • prisma/seed.ts — Seed data (datacenter locations, grid boundaries, AI milestones)
  • src/app/ — Next.js App Router pages
  • src/components/ — React components (ui/, map/, charts/, dashboard/, layout/)
  • src/lib/api/ — EIA and FRED API clients with Zod schemas
  • src/actions/ — Server Actions (typed server-to-client boundary)
  • docker-compose.yml — PostgreSQL 18 + PostGIS 3.5