docs: complete project research

This commit is contained in:
2026-04-02 15:30:56 +02:00
parent 8fdab4b796
commit 0b72f1c305
5 changed files with 1204 additions and 1010 deletions

View File

@@ -1,234 +1,277 @@
# Stack Research
**Domain:** Personal finance dashboard UI overhaul — React SPA
**Researched:** 2026-03-16
**Domain:** Personal finance dashboard — v2.0 wizard setup, auto-budget creation, sharp pastel design system
**Researched:** 2026-04-02
**Confidence:** HIGH
---
## Context: What Already Exists
## Context: What Already Exists (Do Not Re-Research)
This is a subsequent-milestone research document. The stack is **locked**. The project uses:
Actual installed versions from `package.json` (not the prior research document, which had aspirational versions):
| Package | Installed Version | Status |
|---------|------------------|--------|
| React | 19.2.4 | Locked |
| Vite | 8.0.0 | Locked |
| Package | Actual Installed Version | Notes |
|---------|-------------------------|-------|
| React | ^19.2.4 | Locked |
| Vite | ^8.0.0 | Locked |
| TypeScript | ~5.9.3 | Locked |
| Tailwind CSS | 4.2.1 | Locked |
| Recharts | **3.8.0** | Locked — already on latest |
| Radix UI (via `radix-ui`) | 1.4.3 | Locked |
| Lucide React | 0.577.0 | Locked |
| next-themes | 0.4.6 | Locked |
| TanStack Query | 5.90.21 | Locked |
| Tailwind CSS | ^4.2.1 | Locked |
| Recharts | **2.15.4** | Locked — NOT 3.x (prior research was wrong) |
| radix-ui | ^1.4.3 | Unified post-June 2025 package |
| lucide-react | ^0.577.0 | Locked |
| next-themes | ^0.4.6 | Locked |
| TanStack Query | ^5.90.21 | Locked |
| react-router-dom | ^7.13.1 | Locked |
| sonner | ^2.0.7 | Locked |
| @supabase/supabase-js | ^2.99.1 | Backend is Supabase, not custom Go |
| i18next + react-i18next | ^25.8.18 / ^16.5.8 | Locked |
The `index.css` already defines a complete OKLCH `@theme inline` color system with category-specific colors (`--color-income`, `--color-bill`, etc.) and chart colors (`--color-chart-1` through `--color-chart-5`). The project uses the `radix-ui` unified package (post-June 2025 migration).
**Backend reality check:** Despite the milestone context referencing "Go 1.25 backend", the project is a Supabase-backed React SPA. There is no Go source code. All backend work happens via Supabase migrations (SQL) and the `@supabase/supabase-js` client. This is authoritative — verified from `package.json` and `supabase/migrations/`.
**No new frameworks or backend dependencies.** This research covers only what to add or lean into for the UI overhaul.
**Form handling reality check:** Current forms (login, register, template items) use vanilla `useState` + `React.FormEvent`. No react-hook-form or zod are installed.
**Design token reality check:** `--radius: 0.625rem` is applied globally and is the source of the "clunky rounded" look. Sharp redesign requires overriding this token.
---
## Recommended Stack: Additions and Patterns
## New Dependencies Required
### shadcn/ui Components to Add
### 1. react-hook-form + zod — Wizard Form Validation
The project has shadcn/ui components already (card, button, input, etc.) but is missing two critical primitives for the redesign.
The wizard-style template setup requires multi-step form state that persists across steps, per-step validation before advancing, and type-safe schema enforcement. Vanilla `useState` breaks down across 4+ wizard steps with interdependent validation.
| Component | Install Command | Purpose | Why |
|-----------|----------------|---------|-----|
| `chart` | `npx shadcn@latest add chart` | `ChartContainer` + `ChartTooltipContent` wrappers | Provides theme-aware chart wrappers that read from CSS variables. Eliminates boilerplate for consistent chart theming across all chart types. Copy-paste into `src/components/ui/chart.tsx`. |
| `accordion` | `npx shadcn@latest add accordion` | Collapsible category sections on dashboard | Built on Radix UI Accordion primitive. WAI-ARIA compliant, keyboard navigable, supports `type="multiple"` to keep multiple groups open. |
| `collapsible` | `npx shadcn@latest add collapsible` | Single collapsible toggle pattern | Alternative to Accordion when only one independent section needs to expand/collapse (simpler than full Accordion). |
**Use react-hook-form 7.72.0 + zod 4.3.6 + @hookform/resolvers 5.2.2.**
**CRITICAL: Recharts v3 + shadcn chart.tsx compatibility.** The project is on Recharts 3.8.0. The official shadcn/ui chart PR (#8486) for Recharts v3 support is not yet merged (as of March 2026). After running `npx shadcn@latest add chart`, the generated `chart.tsx` may need manual fixes:
| Package | Version | Purpose | Why |
|---------|---------|---------|-----|
| `react-hook-form` | 7.72.0 | Multi-step form state, per-field validation | Industry standard for React forms; tiny bundle (9.3kb); uncontrolled inputs avoid re-render storms across wizard steps |
| `zod` | 4.3.6 | Schema validation with TypeScript inference | Zod 4 is stable (released 2025, latest 4.3.6); 14x faster than v3; subpath exports `zod/v4` enable coexistence if needed |
| `@hookform/resolvers` | 5.2.2 | Bridge between zod schemas and react-hook-form | v5.2.2 supports both Zod v3 and v4 with automatic runtime detection |
1. The `ChartContainer` may log `"width(-1) and height(-1) of chart should be greater than 0"` warnings — fix by adding `initialDimension={{ width: 320, height: 200 }}` to the `ResponsiveContainer` inside `chart.tsx`.
2. If TypeScript errors appear on `TooltipProps`, update the import to use `TooltipProps` from `recharts` directly.
3. Community-verified workaround exists in shadcn-ui/ui issue #9892.
**Zod v4 import note:** Use `import { z } from "zod"` (root export maps to v4) unless you need v3 compatibility, then use `import { z } from "zod/v4"` explicitly. The `zodResolver` from `@hookform/resolvers/zod` handles both transparently.
**Confidence: HIGH** — PR #8486 and issue #9892 are the authoritative sources; the fix is a small patch to one file.
**Known issue:** @hookform/resolvers 5.2.1+ has reported edge-case type errors with specific Zod v4 configurations (GitHub issue #813). Use `5.2.2` (published ~February 2026) which addresses this. If type errors appear, verify the import path is `@hookform/resolvers/zod` not a sub-subpath.
**Confidence: HIGH** — Versions verified via npm search results (react-hook-form 7.72.0 published April 2026; zod 4.3.6; @hookform/resolvers 5.2.2). Integration pattern is the standard shadcn/ui documented approach.
---
### Core Charting Patterns (Recharts 3.8.0)
### 2. Wizard/Stepper UI — Custom Component (No External Library)
No new charting libraries are needed. Recharts 3.8.0 is the current stable release and supports all required chart types natively. Three chart types are needed for the dashboard redesign:
shadcn/ui does not include a stepper or wizard component in its official core library. The discussion thread #1422 requesting it has been open for years. However, shadcn/ui's blocks library now includes stepper patterns (as of March 2026 update) built purely with shadcn/ui `Button`, `Badge`, and Tailwind — **no external npm package needed**.
**1. Donut Chart (expense category breakdown)**
**Recommendation: Build a custom `<WizardStepper>` component from shadcn/ui primitives.**
This approach:
- Requires zero new npm packages
- Matches the existing design system exactly (token-driven styling)
- Is 5080 lines of TypeScript — not complex
- Avoids third-party stepper library churn (none are dominant; most are abandoned within 1-2 years)
Pattern:
```tsx
// Already in use. Enrich by:
// - Increasing innerRadius to ~60, outerRadius to ~100 for visual weight
// - Adding paddingAngle={3} for visible segment separation
// - Using stroke="none" (replaces removed blendStroke in v3)
// - Rendering a center label via custom activeShape or absolute-positioned div
<PieChart>
<Pie
data={pieData}
dataKey="value"
cx="50%"
cy="50%"
innerRadius={60}
outerRadius={100}
paddingAngle={3}
stroke="none"
>
{pieData.map((entry) => (
<Cell key={entry.type} fill={categoryColors[entry.type]} />
))}
</Pie>
<Tooltip content={<ChartTooltipContent />} />
</PieChart>
```
// src/components/shared/WizardStepper.tsx
// Steps indicator: array of step objects → renders numbered circles + connecting lines
// Active step gets primary color; completed steps get checkmark icon
// Controlled via `currentStep: number` prop passed down from wizard page
Note: In Recharts v3, `Cell` is deprecated in favor of the `shape` prop and `activeShape`/`inactiveShape` are deprecated in favor of `shape`. Existing `Cell` usage still works; migration is not required for this milestone.
interface Step {
id: string
label: string
}
**2. Vertical Bar Chart (income budget vs actual)**
```tsx
<BarChart data={incomeData}>
<CartesianGrid vertical={false} strokeDasharray="3 3" />
<XAxis dataKey="name" />
<YAxis />
<Bar dataKey="budgeted" radius={[4, 4, 0, 0]} fill="var(--color-muted)" />
<Bar dataKey="actual" radius={[4, 4, 0, 0]} fill="var(--color-income)" />
<Tooltip content={<ChartTooltipContent />} />
</BarChart>
```
**3. Horizontal Bar Chart (spend by category type)**
```tsx
// layout="vertical" turns BarChart into a horizontal bar chart
<BarChart data={categoryData} layout="vertical">
<XAxis type="number" hide />
<YAxis type="category" dataKey="name" width={130} />
<Bar dataKey="budgeted" radius={[0, 4, 4, 0]} fill="var(--color-muted)" />
<Bar dataKey="actual" radius={[0, 4, 4, 0]} fill="var(--color-primary)" />
<Tooltip content={<ChartTooltipContent />} />
</BarChart>
```
**Confidence: HIGH** — All three patterns verified against Recharts official examples and docs.
---
### Tailwind CSS 4 Color System Patterns
The existing `index.css` is already correctly structured with `@theme inline`. The overhaul needs to extend it with:
**1. Richer category colors (more vibrant for charts)**
The current category colors are defined but conservative. For the rich visual style target, increase chroma:
```css
/* Recommended: bump chroma from ~0.14 to ~0.18+ for visual richness */
--color-income: oklch(0.68 0.19 145); /* vivid green */
--color-bill: oklch(0.65 0.19 25); /* vivid orange-red */
--color-variable-expense: oklch(0.70 0.18 55); /* vivid amber */
--color-debt: oklch(0.62 0.20 355); /* vivid rose */
--color-saving: oklch(0.68 0.18 220); /* vivid blue */
--color-investment: oklch(0.65 0.18 285); /* vivid purple */
```
**2. Semantic status tokens for budget comparison**
```css
--color-over-budget: oklch(0.62 0.20 25); /* red-orange for overspend */
--color-on-budget: oklch(0.68 0.19 145); /* green for on-track */
--color-budget-bar-bg: oklch(0.92 0.01 260); /* neutral track for progress bars */
```
**3. Dark theme token set**
The current CSS has no dark mode overrides. With `next-themes` v0.4.6 already installed, dark mode works by toggling `.dark` on `<html>`. Add a dark block:
```css
.dark {
@theme inline {
--color-background: oklch(0.13 0.02 260);
--color-foreground: oklch(0.95 0.005 260);
--color-card: oklch(0.18 0.02 260);
/* ...etc — mirror the light tokens with dark values */
}
interface WizardStepperProps {
steps: Step[]
currentStep: number // 0-based index
}
```
This is optional for the current milestone (desktop-first, dark mode not listed as a goal), but the token structure is already set up for it.
State management: hold `currentStep` in the wizard page component with `useState`. Each step's validation runs via `react-hook-form`'s `trigger(fieldNames)` before `setCurrentStep(n + 1)`.
**Confidence: HIGH**Tailwind CSS 4 `@theme inline` pattern verified against official Tailwind v4 docs.
**Confidence: HIGH**shadcn/ui blocks page confirms stepper patterns are available as copy-paste blocks with no external dependencies (verified March 2026). Zero external library is the correct choice.
---
### Typography Patterns
### 3. shadcn/ui Components to Add
Already uses Inter via `--font-sans`. No new font installations needed. Apply these patterns consistently:
The wizard needs two additional shadcn/ui components not currently installed:
| Pattern | CSS / Tailwind | Where to Use |
|---------|---------------|--------------|
| Tabular numbers | `tabular-nums` (already used in DashboardPage) | All currency amounts, percentages |
| Monospace amounts | `font-mono` | Dense data tables where column alignment matters |
| Numeric font features | `font-feature-settings: "tnum" 1` | When `tabular-nums` alone is insufficient |
| Large metric emphasis | `text-3xl font-bold tracking-tight` | Summary card primary values |
| Muted labels | `text-sm text-muted-foreground` | Section headers, stat labels |
| Component | Install Command | Purpose | Notes |
|-----------|----------------|---------|-------|
| `progress` | `npx shadcn@latest add progress` | Optional step progress bar within wizard header | Built on Radix UI Progress; already themed via CSS vars. Use if linear progress indicator preferred over dot/circle steps. |
| `checkbox` | `npx shadcn@latest add checkbox` | Select/deselect template items in wizard step | Built on Radix UI Checkbox; WAI-ARIA compliant. |
| `scroll-area` | `npx shadcn@latest add scroll-area` | Scrollable category library panel in budget view | Built on Radix UI ScrollArea; consistent cross-browser scrollbar styling. |
The codebase already uses `tabular-nums` on currency values — this is correct and should be applied everywhere financial numbers appear.
The existing `dialog.tsx`, `input.tsx`, `button.tsx`, `select.tsx`, `badge.tsx`, and `skeleton.tsx` are already present and sufficient for the wizard steps and inline library picker.
**Confidence: HIGH**Pattern matches current codebase and Shopify Polaris / Datawrapper typography standards.
**Confidence: HIGH**Verified against current component list in `src/components/ui/`.
---
### Layout Patterns
## Design Token Changes — Sharp Minimal Pastel System
**Summary card grid:**
No new packages are needed. All changes are CSS variable overrides in `src/index.css`.
```tsx
// 4 cards on desktop, 2x2 on tablet, stacked on mobile
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
### Border Radius — The Core Change
The v1.0 design feels "clunky and rounded" because `--radius: 0.625rem` (10px) is applied everywhere. The v2.0 "sharp minimal" direction requires:
```css
/* Sharp edges — change ONE token, affects all shadcn/ui components */
--radius: 0.125rem; /* 2px — sharp but not perfectly square */
/* Alternative: 0rem for fully square (more aggressive) */
```
**Chart row:**
This single change propagates through every shadcn/ui component because they all use `rounded-[var(--radius)]` or similar. No individual component changes needed.
```tsx
// Charts side-by-side on desktop, stacked on mobile
<div className="grid grid-cols-1 gap-6 lg:grid-cols-2">
### Pastel Color Recalibration
The current category colors use L~0.55 (text-weight, too dark for fills and backgrounds). "Clear pastels" in a sharp minimal design system need a two-tier system:
- **Surface pastel** (card backgrounds, highlights): L~0.93-0.96, C~0.04-0.06
- **Accent pastel** (borders, tags, icons): L~0.75-0.80, C~0.10-0.12
- **Text** (labels, amounts): L~0.40-0.50, C~0.15-0.18 (existing values are correct for this)
```css
/* New: pastel surface colors for wizard step indicators, category cards */
--color-income-surface: oklch(0.95 0.04 155);
--color-bill-surface: oklch(0.95 0.04 25);
--color-variable-expense-surface: oklch(0.95 0.04 50);
--color-debt-surface: oklch(0.95 0.05 355);
--color-saving-surface: oklch(0.95 0.04 220);
--color-investment-surface: oklch(0.95 0.04 285);
/* New: accent pastel (for badges, step indicators, borders) */
--color-income-accent: oklch(0.80 0.10 155);
--color-bill-accent: oklch(0.80 0.10 25);
--color-variable-expense-accent: oklch(0.80 0.10 50);
--color-debt-accent: oklch(0.80 0.11 355);
--color-saving-accent: oklch(0.80 0.10 220);
--color-investment-accent: oklch(0.80 0.10 285);
```
**Collapsible category section:**
The existing text-weight category colors (`--color-income`, etc.) remain unchanged — they're already correct for text/icon usage and pass WCAG 4.5:1.
```tsx
// Using shadcn Accordion — one group per CategoryType
<Accordion type="multiple" defaultValue={["income", "bill"]}>
<AccordionItem value="income">
<AccordionTrigger>
{/* Summary row: label + budgeted + actual + delta */}
</AccordionTrigger>
<AccordionContent>
{/* Line item rows */}
</AccordionContent>
</AccordionItem>
</Accordion>
### Minimal Layout Tokens
```css
/* Reduce visual weight for card borders — sharp design reads better with subtle borders */
--color-border: oklch(0.90 0.008 260); /* slightly lighter than current 0.88 */
/* Tighter card padding via CSS custom property (used in PageShell / StatCard) */
/* No token needed — use Tailwind p-4 consistently instead of p-6 */
```
Use `type="multiple"` so users can expand multiple sections simultaneously. Default expand income and variable_expense as the most-checked categories.
**Confidence: HIGH** — Standard shadcn/ui pattern, verified against official docs.
**Confidence: HIGH** — Based on OKLCH perceptual uniformity properties; the lightness/chroma values follow the Evil Martians OKLCH guide for pastel palette design.
---
## What NOT to Use
## Backend Changes — Supabase (Auto-Budget Creation + Template Seeding)
### Auto-Budget Creation
The feature "auto-create monthly budgets from template on first visit" requires:
1. **A Supabase RPC function** (PostgreSQL function called via `.rpc()`) to atomically create a budget + copy template items in a single round-trip. Application-layer logic (JavaScript calling multiple inserts) is fragile across network failures.
```sql
-- New migration: create_budget_from_template(user_id, month_date)
-- Returns the new budget_id
-- Idempotent: if budget for that month already exists, returns existing id
create or replace function create_budget_from_template(
p_user_id uuid,
p_month date -- first day of the target month
)
returns uuid
language plpgsql
security definer -- needed to bypass RLS for the INSERT
as $$
declare
v_template_id uuid;
v_budget_id uuid;
begin
-- Get user's template
select id into v_template_id from templates where user_id = p_user_id limit 1;
if v_template_id is null then return null; end if;
-- Idempotency: return existing budget for this month
select id into v_budget_id
from budgets
where user_id = p_user_id
and start_date = date_trunc('month', p_month)::date
limit 1;
if v_budget_id is not null then return v_budget_id; end if;
-- Create new budget
insert into budgets (user_id, start_date, end_date, currency)
values (
p_user_id,
date_trunc('month', p_month)::date,
(date_trunc('month', p_month) + interval '1 month' - interval '1 day')::date,
(select currency from profiles where id = p_user_id limit 1)
)
returning id into v_budget_id;
-- Copy template items to budget items
insert into budget_items (budget_id, category_id, budgeted_amount, item_tier)
select v_budget_id, ti.category_id, ti.budgeted_amount, ti.item_tier
from template_items ti
where ti.template_id = v_template_id;
return v_budget_id;
end;
$$;
```
Frontend call:
```typescript
const { data: budgetId } = await supabase.rpc('create_budget_from_template', {
p_user_id: user.id,
p_month: `${year}-${month}-01`
})
```
**Why RPC not application layer:** A single RPC is atomic (no partial state if network drops mid-sequence), runs in 1 round-trip instead of 3-4, and the idempotency guard prevents duplicate budgets from double-calls (React StrictMode double-invocation, fast navigation, etc.).
### Template Seeding (Wizard First-Run)
The wizard "pre-filled common items" require a static list seeded client-side — no backend change needed. The wizard presents checkboxes for ~15 common items (Rent, Salary, Car Insurance, Groceries, etc.) with pre-populated amounts. On wizard completion, one batch `insert` creates the template + template_items. The existing `templates` and `template_items` tables support this without schema changes.
**Categories pre-seeding:** Categories (income, bill, variable_expense, etc.) are per-user, not system-wide. The wizard must also insert default categories before template items can reference them. Order: insert default categories → insert template → insert template_items.
This can also be an RPC (`setup_user_template`) or application-layer batch — the wizard runs once, so network failure risk is acceptable at client-side orchestration.
### Category Library (Inline Add-from-Library)
The `quick_add_items` table stores name + icon only — no amount or category_type. For the inline category library in budget view (replacing the QuickAdd page), the library needs category_type to know which budget section to add to.
**Schema addition needed:**
```sql
-- New migration: add category_type to quick_add_items
alter table quick_add_items
add column category_type category_type, -- existing enum
add column default_amount numeric(12,2) default 0;
```
This enables the library to show items grouped by type and pre-fill amounts when adding to a budget.
**Confidence: MEDIUM** — RPC pattern is well-established in Supabase. Schema addition is straightforward. The exact RPC SQL above is a starting point and may need adjustment based on profiles table structure (currency field). Flag for verification in planning phase.
---
## What NOT to Add
| Avoid | Why | Use Instead |
|-------|-----|-------------|
| Nivo | Adds a large bundle, different component API, requires adapting all existing chart code | Recharts 3.8.0 — already installed, sufficient |
| ApexCharts / ECharts | New library dependency, no benefit over Recharts for this scope | Recharts 3.8.0 |
| react-financial-charts | Designed for candlestick / OHLC trading charts, not budget dashboards | Recharts 3.8.0 |
| Recharts 2.x | Project is already on v3.8.0 — never downgrade | Stay on 3.8.0 |
| shadcn `npx shadcn@latest add` for chart without reading the output | The generated chart.tsx requires a manual Recharts v3 patch | Run the add command, then apply the `initialDimension` fix to `ChartContainer` |
| CSS-in-JS for theming | Tailwind v4 `@theme inline` already handles all theming via CSS variables | Extend `index.css` `@theme inline` block |
| Custom progress bar libraries | Raw Tailwind divs with `style={{ width: X% }}` are already used and are sufficient | Keep existing progress bar pattern, improve styling only |
| Framer Motion | Adds bundle weight; CSS transitions via `transition-all duration-200` cover needed animations | Tailwind transition utilities |
| React Grid Layout | Drag/resize dashboards are out of scope for this milestone | Standard CSS Grid |
| External stepper library (react-use-wizard, react-step-wizard, stepperize) | None is dominant; all add bundle weight for what is 50 lines of custom code; APIs change | Custom `<WizardStepper>` using shadcn/ui Button + Badge + Tailwind |
| Zod v3 (avoid if installing fresh) | v4 is stable and 14x faster; no reason to use v3 for new code | `zod@4.3.6` |
| Framer Motion for wizard step transitions | 28kb gzip; CSS `transition-opacity duration-200` is sufficient for step fade | Tailwind transition utilities |
| Recharts upgrade to 3.x in this milestone | 2.15.4 is working; v3 migration guide lists breaking changes that would require updating all existing charts; out of scope | Stay on 2.15.4 for v2.0 milestone; plan upgrade separately |
| CSS-in-JS for new design tokens | Tailwind v4 `@theme inline` in `index.css` already handles all theming | Extend `index.css` `@theme inline` block |
| Zustand for wizard state | TanStack Query + useState is already the state pattern in this app; wizard state is local and short-lived | `useState` in wizard page component |
| Supabase Edge Functions for auto-budget | PostgreSQL function (RPC) runs in the same DB transaction; simpler, no Deno runtime | Supabase RPC (pg function) |
---
@@ -236,10 +279,26 @@ Use `type="multiple"` so users can expand multiple sections simultaneously. Defa
| Recommended | Alternative | When to Use Alternative |
|-------------|-------------|-------------------------|
| Recharts 3.8.0 (stay) | Nivo | If you needed animated, visually opinionated charts with server-side rendering — not applicable here |
| shadcn Accordion | KendoReact PanelBar | If the project used KendoReact's broader component suite — it doesn't |
| Tailwind `tabular-nums` | Geist Mono font | Use Geist Mono only if building a dense trading-style table where column alignment is a core feature, not a budget dashboard |
| shadcn chart.tsx (copy-paste) | Direct Recharts usage | Acceptable — the project's existing dashboard already uses Recharts directly. shadcn wrappers add theme-aware tooltips and config-based colors but are not mandatory |
| Custom WizardStepper | `react-use-wizard` (npm) | If wizard logic were complex (branching paths, async steps with external dependencies) — this wizard is linear with simple validation |
| Zod 4 | Valibot | If bundle size were critical (Valibot is ~1kb vs Zod's ~14kb) — not a concern here |
| Supabase RPC for auto-budget | Application-layer multi-insert | Acceptable if you tolerate partial failure risk and handle retry logic — RPC is cleaner |
| Two-tier OKLCH pastel tokens | Single token set | If the design only needed chart colors — the wizard and library UI need surface pastels that the existing single-tier system doesn't provide |
---
## Installation
```bash
# Wizard form validation (new packages)
bun add react-hook-form@7.72.0 zod@4.3.6 @hookform/resolvers@5.2.2
# New shadcn/ui components
npx shadcn@latest add progress
npx shadcn@latest add checkbox
npx shadcn@latest add scroll-area
```
No other npm/bun installs needed. All other new functionality (wizard stepper UI, design token changes, Supabase RPC, schema migration) is implemented via local code and SQL.
---
@@ -247,43 +306,59 @@ Use `type="multiple"` so users can expand multiple sections simultaneously. Defa
| Package | Version | Compatible With | Notes |
|---------|---------|-----------------|-------|
| Recharts | 3.8.0 | React 19 | Requires `react-is` peer dependency override for React 19 |
| shadcn chart.tsx | CLI generated | Recharts 3.8.0 | Apply `initialDimension` fix to `ChartContainer` after generation |
| Tailwind CSS | 4.2.1 | `@theme inline` | Use `@theme inline` (not bare `@theme`) when referencing other CSS vars |
| next-themes | 0.4.6 | React 19 | Compatible; dark mode toggled via `.dark` class on `<html>` |
| radix-ui | 1.4.3 | Post-June 2025 migration | shadcn CLI add commands now generate imports from `radix-ui`, not `@radix-ui/react-*` |
| react-hook-form | 7.72.0 | React 19 | Fully compatible; hooks-based, no legacy API |
| zod | 4.3.6 | TypeScript ~5.9.3 | Requires TypeScript 4.5+; project is on 5.9.3 — fine |
| @hookform/resolvers | 5.2.2 | react-hook-form 7.x + zod 4.x | Automatic v3/v4 Zod detection |
| Recharts | 2.15.4 | React 19 | Stays on v2; DO NOT upgrade in this milestone |
| Tailwind CSS | 4.2.1 | `@theme inline` | Sharp radius via `--radius: 0.125rem` in `@theme inline` block |
| radix-ui | 1.4.3 | shadcn new-york style | New shadcn add commands generate `radix-ui` imports (unified package), not `@radix-ui/*` |
---
## Installation
## Integration Points
```bash
# Add shadcn chart primitives (then apply Recharts v3 fix to chart.tsx)
npx shadcn@latest add chart
### Wizard → Template → Budget Flow
# Add Accordion for collapsible dashboard sections
npx shadcn@latest add accordion
```
WizardPage (new route: /setup)
└─ react-hook-form (FormProvider wrapping all steps)
└─ WizardStepper component (step indicator)
└─ Step 1: Pick categories (checkbox + default amounts)
└─ Step 2: Adjust fixed items (input fields, pre-filled)
└─ Step 3: Adjust variable items
└─ Step 4: Review + confirm
└─ onSubmit → batch insert categories + template + template_items
└─ redirect to /dashboard
# Add Collapsible if single-section toggles are needed
npx shadcn@latest add collapsible
DashboardPage (existing)
└─ on mount: check if budget exists for current month
└─ if not: call supabase.rpc('create_budget_from_template', { month })
└─ render budget data (existing pattern, improved display)
BudgetDetailPage (existing, enhanced)
└─ inline category library panel (uses scroll-area + checkbox/button)
└─ add one-off items directly from library
```
No npm/bun package installs needed — Recharts 3.8.0 is already installed and sufficient.
### Design Token Change Impact
The `--radius` change in `index.css` requires no component-level changes — all shadcn/ui components use the token automatically. The new surface/accent OKLCH tokens need to be applied explicitly in new components (wizard steps, category library cards); existing components are unaffected.
---
## Sources
- [Recharts GitHub Releases](https://github.com/recharts/recharts/releases) — version 3.8.0 confirmed latest stable (March 2025)
- [Recharts 3.0 Migration Guide](https://github.com/recharts/recharts/wiki/3.0-migration-guide) — breaking changes from v2 to v3
- [shadcn/ui Chart Docs](https://ui.shadcn.com/docs/components/chart) — ChartContainer, ChartConfig, ChartTooltip patterns
- [shadcn-ui/ui PR #8486](https://github.com/shadcn-ui/ui/pull/8486) — Recharts v3 chart.tsx upgrade (open as of March 2026)
- [shadcn-ui/ui Issue #9892](https://github.com/shadcn-ui/ui/issues/9892) — Community-verified Recharts v3 chart.tsx fix
- [shadcn/ui Accordion Docs](https://ui.shadcn.com/docs/components/radix/accordion) — component API verified
- [Tailwind CSS v4 Theme Docs](https://tailwindcss.com/docs/theme) — `@theme inline`, CSS variables, OKLCH palette
- [npm recharts](https://www.npmjs.com/package/recharts) — 3.8.0 current, 7M weekly downloads, healthy maintenance
- npm search results (April 2026) — react-hook-form 7.72.0, zod 4.3.6, @hookform/resolvers 5.2.2
- [zod.dev/v4](https://zod.dev/v4) — Zod 4 stable release notes, versioning strategy
- [shadcn/ui blocks page](https://ui.shadcn.com/blocks) — Confirmed no native stepper component; patterns available as copy-paste blocks (no npm dep)
- [shadcn-ui/ui Discussion #1422](https://github.com/shadcn-ui/ui/discussions/1422) — Feature request for stepper (still open as of April 2026)
- [react-hook-form/resolvers GitHub](https://github.com/react-hook-form/resolvers/releases) — v5.2.2 Zod v4 support
- [github.com/recharts/recharts/wiki/3.0-migration-guide](https://github.com/recharts/recharts/wiki/3.0-migration-guide) — v3 breaking changes confirming upgrade is out of scope for this milestone
- [evilmartians.com — Better dynamic themes with OKLCH](https://evilmartians.com/chronicles/better-dynamic-themes-in-tailwind-with-oklch-color-magic) — OKLCH lightness/chroma guidance for pastel systems
- `package.json` in project root — authoritative source for actual installed versions (Recharts 2.15.4, not 3.x as prior research stated)
- `supabase/migrations/` — authoritative source confirming Supabase backend, existing schema
---
*Stack research for: SimpleFinanceDash UI Overhaul*
*Researched: 2026-03-16*
*Stack research for: SimpleFinanceDash v2.0 — Wizard Setup, Auto-Budget, Sharp Pastel Design*
*Researched: 2026-04-02*