← back to Norma
CLAUDE.md
135 lines
# Norma Intelligence Platform
## FIRST ACTION EVERY SESSION
1. Read `docs/sessions/sessions.md` — show user the most recent session summary
2. Read `docs/sessions/learnings.md` — apply all learnings to current work
3. Read `docs/sessions/tasks-requested.md` — check for pending tasks
4. Before EVERY action, check learnings.md for relevant gotchas
## Project Info
- **Directory**: /root/Projects/Norma/
- **Port**: 7400 | **PM2**: norma-email
- **Database**: connection string lives in `.env.local` (DATABASE_URL); use `dw_admin@127.0.0.1:5432/sdcc`. NEVER commit credentials to docs.
- **Auth**: admin / (BASIC_AUTH env — see .env.local; no longer hardcoded)
- **Stack**: Next.js 16 (App Router) + Tailwind 4 + PostgreSQL
- **Gmail**: natalia@studentdebtcrisis.org (OAuth connected, GCP: norma-490521)
## Session Tracking — MANDATORY
- **Sessions**: `docs/sessions/sessions.md` — append summary after every session
- **Tasks Requested**: `docs/sessions/tasks-requested.md` — log every user request
- **Tasks Completed**: `docs/sessions/tasks-completed.md` — log completed work with files
- **Learnings**: `docs/sessions/learnings.md` — append technical learnings after every session
- **On session end**: commit all files, append to all 4 docs, push to git
## Purpose
Multi-tenant nonprofit intelligence platform powered by Norma.
Three-tier UI: Norma (admin), Nikki (org staff), Pulse (end user).
Email & Outreach Center, Gmail CRM, News Intelligence, Petition Management.
## Key Files
- lib/db.ts -- Postgres pool
- lib/auth.ts -- Cookie auth
- lib/audit.ts -- Audit logger
- lib/export.ts -- EML/HTML/TXT export
- lib/boilerplate.ts -- One-click insert blocks
- lib/brand.ts -- Norma brand config
- db/schema.sql -- Full schema
- db/seed.sql -- Sample data
---
## Figma Design System Rules
### Design Tokens (CSS Variables)
IMPORTANT: Never hardcode colors — always use CSS variables from `app/globals.css`:
| Token | Value | Usage |
|-------|-------|-------|
| `--color-bg` | #0C0F1A | Page background |
| `--color-surface` | #131829 | Card/panel background |
| `--color-surface-el` | #1C2237 | Elevated surface (inputs, hover) |
| `--color-primary` | #10b981 | Brand emerald, buttons, links |
| `--color-primary-hover` | #059669 | Button hover state |
| `--color-secondary` | #f59e0b | Amber accent |
| `--color-lane-a` | #f43f5e | Petition lane (rose) |
| `--color-lane-b` | #6366f1 | Policy lane (indigo) |
| `--color-lane-c` | #10b981 | Resources lane (emerald) |
| `--color-success` | #10b981 | Success states |
| `--color-warning` | #f59e0b | Warning states |
| `--color-error` | #f43f5e | Error states |
| `--color-text` | #f0f0f5 | Primary text |
| `--color-text-secondary` | #a1a1b5 | Secondary text |
| `--color-text-muted` | #6B7280 | Muted/disabled text |
| `--color-border` | #2A3048 | Borders, dividers |
Radius: `--radius-sm` (6px), `--radius-md` (10px), `--radius-lg` (14px)
Transition: `--transition` (150ms ease)
### Component Classes (globals.css)
Use these pre-defined classes — do NOT recreate them:
- `.card` / `.card-elevated` — Card containers
- `.btn` + `.btn-primary` / `.btn-secondary` / `.btn-danger` / `.btn-ghost` — Buttons
- `.btn-sm` / `.btn-lg` — Button sizes
- `.badge` + `.badge-success` / `.badge-warning` / `.badge-error` — Status badges
- `.lane-a` / `.lane-b` / `.lane-c` — Lane-specific badges
- `.input` — Form inputs with focus ring
- `.spinner` — Loading spinner
- `.skeleton` — Shimmer loading placeholder
- `.divider` — Horizontal rule
### Component Organization
| Location | Contents |
|----------|----------|
| `components/` | Shared: AppShell, Sidebar, AuthProvider, ToastProvider, ChatPanel |
| `components/drafts/` | DraftsTab and sub-components |
| `components/grants/` | GrantsTab, FundingExplorer |
| `components/settings/` | SettingsTab |
| `components/shared/` | Reusable: SortDropdown |
| `hooks/` | useDebounce, useClientSort |
| `lib/` | DB, auth, audit, chat, slack utilities |
| `app/api/` | Next.js API routes |
### Icon System
- IMPORTANT: Use `lucide-react` for ALL icons — do not add other icon packages
- Import individual icons: `import { Search, Plus } from 'lucide-react'`
- Standard sizes: 12 (badge), 14-16 (button), 18-20 (card), 24 (header)
- Icons accept `size`, `color`, `className` props
### Styling Approach
1. Use CSS classes from `globals.css` for standard elements (card, btn, badge, input)
2. Use Tailwind utility classes for layout (flex, gap, grid, p-4, etc.)
3. Use inline `style={{}}` for dynamic values, CSS variables, or one-off positioning
4. IMPORTANT: Dark theme only — `color-scheme: dark` is set globally
5. Framer Motion (`motion` from `framer-motion`) used for animations in tab components
### Figma MCP Integration Flow
When implementing designs from Figma:
1. Run `get_design_context` for the node
2. Run `get_screenshot` for visual reference
3. Map Figma colors → Norma CSS variables (see token table above)
4. Reuse `.card`, `.btn-*`, `.badge-*`, `.input` classes
5. Icons from lucide-react only
6. Validate against screenshot for 1:1 parity
### Asset Handling
- IMPORTANT: If Figma MCP returns localhost asset URLs, use them directly
- DO NOT import new icon packages — all icons come from lucide-react
- Static assets go in `public/`
### Architecture Patterns
- All components are `'use client'` (client-side rendering)
- Database: `import { query } from '@/lib/db'` — returns `{ rows }` via pg Pool
- Auth: Cookie-based with `norma-auth` cookie name
- Audit: `import { auditLog } from '@/lib/audit'` — logs all actions
- Toast: `import { useToast } from '@/components/ToastProvider'` → `addToast()`
- Sort: `import { useClientSort } from '@/hooks/useClientSort'` for client-side sorting
- AI: Gemini 2.0 Flash via `generativelanguage.googleapis.com` API