docs: complete project research
This commit is contained in:
@@ -1,200 +1,183 @@
|
||||
# Project Research Summary
|
||||
|
||||
**Project:** SimpleFinanceDash — UI/UX Overhaul Milestone
|
||||
**Domain:** Personal finance budget dashboard (React SPA, UI-only redesign)
|
||||
**Researched:** 2026-03-16
|
||||
**Project:** SimpleFinanceDash v2.0 — Wizard Setup, Auto-Budget Creation, Sharp Pastel Design
|
||||
**Domain:** Personal finance dashboard — React SPA with Supabase backend
|
||||
**Researched:** 2026-04-02
|
||||
**Confidence:** HIGH
|
||||
|
||||
## Executive Summary
|
||||
|
||||
This milestone is a pure UI/UX overhaul of an existing working application. The backend (Supabase schema, hooks, queries) is frozen. The stack is already in place — React 19, Vite 8, Tailwind CSS 4, Recharts 3.8.0, shadcn/ui, TanStack Query — and no new framework dependencies are needed. The overhaul adds three shadcn/ui primitives (`chart`, `accordion`/`collapsible`), extends the existing OKLCH color system, and introduces a structured component hierarchy for the dashboard. The core transformation is from a flat single-chart dashboard to a rich hybrid layout: summary KPI cards, three chart types (donut, vertical bar, horizontal bar), and collapsible per-category line-item sections.
|
||||
SimpleFinanceDash v2.0 is a UX simplification milestone on top of a fully working v1.0 app. All data infrastructure already exists — categories, templates, budget generation, charts, collapsible sections. The central problem is cognitive: new users land on a blank dashboard with no guidance, monthly budget creation requires a manual trigger, and the Quick Add feature lives on a disconnected page. The recommended approach is a three-part simplification: (1) a 3-step first-run wizard that seeds a usable template from curated defaults, (2) automatic monthly budget creation on dashboard visit when a template is populated, and (3) inline item-adding directly from the budget view to replace the isolated Quick Add page. Paired with a design system token rework (sharp radius, clearer pastels), these changes transform the app from a data entry tool into a coherent, guided experience.
|
||||
|
||||
The recommended approach is to establish design foundations first (tokens, shared components, build order primitives) before touching any page. Every visual decision — color, spacing, card style — must originate from `index.css` `@theme inline` tokens and a small set of shared components (`PageShell`, `StatCard`, `CategorySection`). Without this discipline, a multi-page overhaul will produce "island redesign" inconsistency: each page looks polished individually but the app feels fragmented during navigation. The dashboard phase comes second, followed by extending the design system to all remaining pages.
|
||||
The stack is locked and healthy. The only new dependencies are react-hook-form 7.72.0, zod 4.3.6, and @hookform/resolvers 5.2.2 for multi-step form validation in the wizard. Three additional shadcn/ui components are needed (progress, checkbox, scroll-area). All other work — the wizard stepper UI, design token changes, auto-budget triggering — is implemented through local code changes and SQL with no additional packages. Critically, no new DB migrations are required for features: all wizard and auto-budget writes go to existing `categories`, `template_items`, `budgets`, and `budget_items` tables via existing hooks and mutations. Two DB constraint migrations are required for safety (unique constraint on `budgets(user_id, start_date)` and `categories(user_id, name)`), and a one-time migration to set `profiles.setup_completed = true` for existing v1.0 users.
|
||||
|
||||
The highest-risk technical area is the Recharts + shadcn `chart.tsx` integration: the official shadcn PR for Recharts v3 is not yet merged, so the generated `chart.tsx` requires a known manual patch (add `initialDimension` to `ResponsiveContainer`). A close second risk is collapsible section layout shift — Recharts `ResponsiveContainer` instances react to parent height changes, and multiple instances on one page require `debounce={50}` and Radix `Collapsible` (not raw `display:none` toggle) to prevent ResizeObserver cascade errors. Both risks have documented fixes and are LOW recovery cost if addressed proactively.
|
||||
|
||||
---
|
||||
The primary risks are concurrency-related and data-integrity-related, not technical. Auto-budget creation via a client-side `useEffect` can fire multiple times (React StrictMode double-invocation, multi-tab, fast navigation), producing duplicate budget rows without a DB-level unique constraint. The wizard completion sequence is non-idempotent without explicit guards — a re-run creates duplicate categories and template items. The design token rework is a third systemic risk: changing global CSS variables (`--radius`, OKLCH color tokens) affects all 9 existing pages simultaneously. All three risks have clear, low-cost mitigations that must be applied before the relevant features ship, not after.
|
||||
|
||||
## Key Findings
|
||||
|
||||
### Recommended Stack
|
||||
|
||||
The stack is locked; no new npm packages are required. Three shadcn/ui components must be installed via CLI: `chart` (Recharts theme-aware wrappers), `collapsible` (Radix primitive for category sections), and optionally `accordion`. After running `npx shadcn@latest add chart`, a manual one-line fix to `chart.tsx` is required: add `initialDimension={{ width: 320, height: 200 }}` to the inner `ResponsiveContainer` (see shadcn-ui/ui issue #9892). The existing OKLCH color palette in `index.css` needs only two additions: richer chroma on category colors (bump from ~0.14 to ~0.18+) and semantic status tokens (`--color-over-budget`, `--color-on-budget`, `--color-budget-bar-bg`).
|
||||
The project runs on React 19 + Vite 8 + TypeScript 5.9 + Tailwind CSS 4 + Recharts 2.15.4 + TanStack Query v5 + Supabase (PostgreSQL + Auth + RLS). These versions are locked and must not be changed in this milestone. Note: prior research incorrectly listed Recharts 3.x — the actual installed version is 2.15.4 per `package.json`, and upgrading to v3 is explicitly out of scope due to breaking changes. The backend is Supabase, not a Go service — there is no Go source code in the repository.
|
||||
|
||||
**Core technologies and their roles for this milestone:**
|
||||
- **Recharts 3.8.0** — all three chart types (donut, bar, horizontal bar) are supported natively; stay on current version, do not introduce alternative chart libraries
|
||||
- **shadcn `chart.tsx`** — `ChartContainer` + `ChartTooltipContent` wrappers provide CSS-variable-aware theming for all Recharts instances; required patch documented in issue #9892
|
||||
- **shadcn `Collapsible`** — Radix UI primitive that animates height via CSS custom property `--radix-collapsible-content-height`; the correct tool for per-category collapsible sections
|
||||
- **Tailwind CSS 4 `@theme inline`** — single source of truth for all color tokens; all component color values must reference CSS variables, never hardcoded hex
|
||||
- **`useMemo` in DashboardContent** — all chart data derivations must be memoized centrally; child chart components receive pre-computed data arrays and render only
|
||||
|
||||
**Critical version note:** Recharts 3 deprecated `Cell` in favor of `shape` prop, and removed `blendStroke` — use `stroke="none"` instead. Existing `Cell` usage still works but should not be extended.
|
||||
**Core technologies (new additions only):**
|
||||
- `react-hook-form 7.72.0` + `zod 4.3.6` + `@hookform/resolvers 5.2.2` — multi-step wizard form validation; industry standard, 9.3kb bundle, handles per-step validation before advancing
|
||||
- `shadcn checkbox`, `progress`, `scroll-area` — three new shadcn components needed for wizard and inline add panel
|
||||
- Custom `<WizardStepper>` built from shadcn/ui `Button` + `Badge` + Tailwind — no external stepper library; none are dominant and all add bundle weight for 50 lines of local code
|
||||
- OKLCH two-tier pastel token system in `src/index.css` — surface tokens at L~0.95 for backgrounds, accent tokens at L~0.80 for borders/badges, existing text tokens at L~0.55 unchanged
|
||||
|
||||
### Expected Features
|
||||
|
||||
Research grounded in competitor analysis (YNAB, Empower) and fintech UX standards. The full feature list lives in `FEATURES.md`.
|
||||
**Must have (table stakes — v2.0 launch):**
|
||||
- 3-step first-run wizard: income → common items (pre-filled, editable, with live running balance) → review — skippable per step and as a whole
|
||||
- Pre-seeded library of ~15-20 curated items grouped by category type with static sensible default amounts
|
||||
- Auto-create current month's budget from template on dashboard visit — silent, no manual trigger
|
||||
- First-creation toast notification only ("Your April budget was created from your template"); silent for all subsequent months
|
||||
- Inline add-from-library on budget view as a shadcn Sheet panel — replaces the standalone Quick Add page
|
||||
- Quick Add removed from sidebar navigation; route kept with redirect to `/budgets`
|
||||
- Dashboard summary cards correctly reflecting current month budget data
|
||||
- Empty state CTAs for: empty template page, empty dashboard, empty budget view
|
||||
|
||||
**Must have (table stakes — users expect these):**
|
||||
- Summary KPI cards (income / expenses / balance) with colored semantics and variance badges
|
||||
- Donut chart with center total label and active hover expand
|
||||
- Horizontal bar chart: budget vs actual per category type
|
||||
- Grouped bar chart: income budgeted vs actual
|
||||
- Collapsible per-category sections with line items and group totals
|
||||
- Skeleton loading states that mirror the real layout structure
|
||||
- Month navigation control on the dashboard (currently locked to current month)
|
||||
- Consistent design language across all pages — the dashboard sets the pattern, all other pages must inherit it
|
||||
**Should have (competitive differentiators — v2.x):**
|
||||
- "Edit template" shortcut link from budget view for quick access to change recurring items
|
||||
- Persistent "this month" summary widget on the dashboard sidebar
|
||||
- "Complete setup" banner for users who skipped the wizard but have an empty template
|
||||
- Running balance updating live during wizard item selection (income minus sum of selected items; frontend computation only)
|
||||
|
||||
**Should have (differentiators, high value for low cost):**
|
||||
- Variance indicators (delta arrows/badges) on summary cards and section headers
|
||||
- Accent-colored category section borders (`border-l-4` with category CSS variable)
|
||||
- Empty state with actionable CTA for new months
|
||||
- Carryover amount surfaced on the dashboard balance card
|
||||
- Section collapse state preserved in localStorage (P3 polish)
|
||||
|
||||
**Defer to v2+:**
|
||||
- Trend / multi-month charts — requires new query shape and chart layout; explicitly out of scope
|
||||
- Dark mode — OKLCH infrastructure is ready but requires full contrast audit; doubles testing surface
|
||||
- AI-derived insights — backend dependency; no scope here
|
||||
- Drag-to-reorder categories — requires `sort_order` mutation support
|
||||
**Defer (v3+):**
|
||||
- AI-suggested amounts based on spending history — requires historical data and ML infrastructure; static defaults are sufficient
|
||||
- CSV/bank import for actuals — already noted as a future feature in PROJECT.md
|
||||
- Mandatory wizard / forced onboarding — explicitly an anti-feature; skippable is always correct
|
||||
- Complex 6+ step wizard — drop-off increases sharply beyond step 3; confirmed by YNAB's own Oct 2025 update to shorten their onboarding
|
||||
|
||||
### Architecture Approach
|
||||
|
||||
The existing three-tier architecture (Pages → Hooks → Supabase) is preserved intact. The overhaul introduces a **View Components layer** that sits between pages and shadcn/ui primitives, and a small **Shared Components layer** for cross-page patterns. Hooks and library files are read-only during this milestone; all computation lives in the presentation layer via `useMemo`.
|
||||
The v2.0 architecture is additive, not structural. A new `WizardRoute` guard wraps the existing `ProtectedRoute` subtree in `App.tsx`. A new `/setup` route renders `SetupWizardPage` as a dedicated page (not a modal overlay — dedicated URL prevents broken refresh/back behavior). The wizard completes by writing to existing tables via existing hooks. Auto-budget creation is a `useEffect` trigger added to `DashboardPage` that calls the already-existing `generateFromTemplate` mutation. Inline add replaces `QuickAddPicker` with a new `AddOneOffSheet` component at both call sites. Dashboard simplification removes the 3-column chart grid from `DashboardContent` (charts stay in the codebase but are removed from the Dashboard layout). All existing hooks and mutations (`useBudgets.ts`, `useTemplate.ts`, `useCategories.ts`, etc.) are read-only for this milestone.
|
||||
|
||||
**New components and their responsibilities:**
|
||||
**New files:**
|
||||
1. `src/hooks/useFirstRunState.ts` — detects first-run: `categories.length === 0 OR template_items.length === 0`
|
||||
2. `src/data/presets.ts` — static preset category list with suggested amounts (compile-time data, no DB table)
|
||||
3. `src/pages/SetupWizardPage.tsx` — 3-step wizard, local `useState` only, localStorage persistence
|
||||
4. `src/components/wizard/WizardStep.tsx`, `CategoryDefaults.tsx`, `TemplateDefaults.tsx` — wizard UI pieces
|
||||
5. `src/components/budget/AddOneOffSheet.tsx` — Sheet-based one-off item adder (replaces QuickAddPicker)
|
||||
|
||||
| Component | Location | Responsibility |
|
||||
|-----------|----------|----------------|
|
||||
| `DashboardContent` | `components/dashboard/` | Orchestrator: owns `useMemo` derivations, passes typed props to all children |
|
||||
| `SummaryStrip` + `StatCard` | `components/dashboard/` | KPI cards row with semantic color and variance badge |
|
||||
| `ChartPanel` | `components/dashboard/` | Two-column responsive grid containing all three chart instances |
|
||||
| `IncomeBarChart` | `components/dashboard/` | Budgeted vs actual income vertical bar, wrapped in `ChartContainer` |
|
||||
| `ExpenseDonutChart` | `components/dashboard/` | Expense breakdown donut with center total and custom legend |
|
||||
| `SpendBarChart` | `components/dashboard/` | Horizontal budget vs actual by category type |
|
||||
| `CategorySection` | `components/dashboard/` | Radix `Collapsible` wrapping header row + `BudgetLineItems` |
|
||||
| `BudgetLineItems` | `components/dashboard/` | Line-item table reusing existing `InlineEditCell` / `DifferenceCell` atoms |
|
||||
| `PageShell` | `components/shared/` | Cross-page consistent header with title, optional description, CTA slot |
|
||||
|
||||
**Build order is strictly dependency-driven** (see Architecture section for full sequence): install shadcn primitives first, then `PageShell` and `StatCard`, then chart components, then `CategorySection`, then `DashboardContent` as final orchestrator, then all remaining page refreshes.
|
||||
**Modified files:** `src/App.tsx`, `src/components/AppLayout.tsx`, `src/pages/DashboardPage.tsx`, `src/pages/BudgetDetailPage.tsx`, `src/index.css`, `src/i18n/en.json`, `src/i18n/de.json`
|
||||
|
||||
### Critical Pitfalls
|
||||
|
||||
All six pitfalls in `PITFALLS.md` are rated HIGH confidence with verified fixes. The top five to actively prevent:
|
||||
1. **Duplicate budget creation on concurrent auto-create** — Add `UNIQUE (user_id, start_date)` constraint to `budgets` table via migration AND use `INSERT ... ON CONFLICT DO NOTHING` in `generateFromTemplate` before any auto-create code ships. Use a `useRef(false)` guard in the `useEffect` to prevent double-fire from React StrictMode.
|
||||
|
||||
1. **Unmemoized chart data triggers triple re-renders** — every `items.filter().reduce()` in `DashboardContent` must be wrapped in `useMemo`. Adding three chart instances to a non-memoized render body multiplies re-render cost 3x and causes tooltip hover lag. Recovery cost is LOW but disrupts delivered work if caught late.
|
||||
2. **Wizard creates duplicate categories on re-run** — Add `UNIQUE (user_id, name)` constraint to `categories` table; use upsert for category creation. Add `profiles.setup_completed` boolean; set to `true` in `onSuccess` only. Write a migration to backfill `setup_completed = true` for all v1.0 users with existing template items before shipping.
|
||||
|
||||
2. **shadcn `chart.tsx` incompatibility with Recharts 3** — the generated `chart.tsx` from `npx shadcn@latest add chart` will produce `width(-1) and height(-1)` warnings and potential layout failures. Apply the `initialDimension` fix to `ChartContainer` immediately after generation. This is a one-line fix with a documented workaround (issue #9892), but if skipped it causes all charts to silently render at zero dimensions.
|
||||
3. **Design token rework breaks all 9 pages silently** — Token changes must be one isolated commit followed immediately by a full visual regression pass on all pages before any component code is touched. Never mix token changes and component changes in the same commit.
|
||||
|
||||
3. **Collapsible sections trigger ResizeObserver cascade on charts** — using `display:none` toggle or raw `height` animation on category sections causes Recharts `ResponsiveContainer` instances above/below to rapidly resize. Fix: use Radix `Collapsible` with CSS `@keyframes` on `--radix-collapsible-content-height`, and add `debounce={50}` to all `ResponsiveContainer` instances.
|
||||
4. **Auto-budget defaults to wrong currency** — The `generateFromTemplate` mutation defaults to `"EUR"`. Auto-create must read `profile.currency` first and chain via TanStack Query's `enabled` flag: only auto-create after both the budgets list and user profile are loaded.
|
||||
|
||||
4. **Color accessibility regression during "rich visual" overhaul** — the redesign goal of rich colors is a direct risk factor for WCAG contrast failures. The existing `text-green-600` / `text-red-600` pattern must be audited (green-600 is borderline). All six category pie slice colors cluster at similar OKLCH lightness (~0.65–0.72) — vary lightness as well as hue. Supplement color with icons for status indicators; color alone is never sufficient.
|
||||
|
||||
5. **i18n key regressions** — `i18next` silently falls back to English when German keys are missing (`fallbackLng: 'en'`). Every new UI text key must be added to both `en.json` and `de.json` in the same commit. Run `i18next-scanner` or manually switch to German locale before marking any phase complete.
|
||||
|
||||
**Sixth pitfall to prevent at the outset:** Design inconsistency across page refreshes. If shared components (`StatCard`, `CategorySection` header pattern, card border accents) are not extracted before page work begins, each page will develop subtle visual drift that is expensive to correct retroactively.
|
||||
|
||||
---
|
||||
5. **Wizard state lost on browser refresh** — Persist wizard state to `localStorage` keyed by `wizard_state_${userId}` on every step change; read on mount; clear on completion or skip. Use URL search params (`?step=2`) for browser back/forward support.
|
||||
|
||||
## Implications for Roadmap
|
||||
|
||||
Research points to a clear four-phase structure. The ordering is driven by: (1) the build dependency chain in ARCHITECTURE.md, (2) the "design foundation before page work" principle from PITFALLS.md, and (3) the feature dependency graph in FEATURES.md.
|
||||
Research points to a clear five-phase structure derived from the dependency chain in ARCHITECTURE.md, the feature dependency graph in FEATURES.md, and the phase-to-pitfall mapping in PITFALLS.md.
|
||||
|
||||
### Phase 1: Design Foundation and Primitives
|
||||
**Rationale:** Multiple pitfalls converge on the same root cause — design tokens and shared components must exist before any page work begins. Design drift (Pitfall 6) and color accessibility failures (Pitfall 4) both require the palette and shared component abstractions to be established first. This phase has no external dependencies and produces the building blocks every subsequent phase consumes.
|
||||
**Delivers:** Extended `index.css` color tokens (richer chroma, semantic status tokens), installed shadcn primitives (`chart.tsx` with Recharts v3 patch applied, `collapsible.tsx`), `PageShell`, `StatCard` / `SummaryStrip` components.
|
||||
**Addresses:** Summary KPI cards (table stakes), accent-colored category borders, semantic color system, skeleton components
|
||||
**Avoids:** Design inconsistency pitfall, color accessibility regression, CSS variable scope issues
|
||||
**Research flag:** Standard patterns — no additional research needed. Tailwind v4 `@theme inline` and WCAG contrast requirements are well-documented.
|
||||
### Phase 1: Design System Token Rework
|
||||
**Rationale:** Token changes cascade globally to all 9 existing pages. This must land first, in isolation, establishing the visual baseline before any page component is built or modified. Mixing token changes with component changes makes regressions impossible to attribute.
|
||||
**Delivers:** `--radius: 0.125rem` (sharp edges), refined OKLCH pastel surface/accent tokens, warmer background, softer border — applied in `src/index.css` only, zero component-file changes.
|
||||
**Addresses:** Sharp minimal aesthetic direction; OKLCH two-tier pastel system for category colors
|
||||
**Avoids:** Pitfall 3 (token rework breaks pages silently) — full visual pass on all 9 pages is the acceptance criterion before this phase closes.
|
||||
**Research flag:** Standard pattern — CSS custom property overrides in Tailwind v4 `@theme inline` are fully documented. No deeper research needed.
|
||||
|
||||
### Phase 2: Dashboard Charts and Layout
|
||||
**Rationale:** Charts depend on `chart.tsx` from Phase 1. The dashboard is the highest-value page and establishes the full visual language for all subsequent pages. Month navigation must be included here (not deferred) because it changes how `DashboardContent` holds state — retrofitting it after collapsible sections are built is more disruptive than including it upfront.
|
||||
**Delivers:** `DashboardContent` orchestrator with `useMemo` data derivations, `ChartPanel` with all three chart types (`IncomeBarChart`, `ExpenseDonutChart`, `SpendBarChart`), month navigation control, skeleton loading for charts and cards.
|
||||
**Addresses:** Donut chart (table stakes), horizontal bar chart (P1), grouped income bar chart (P1), skeleton loading (P1), month navigation (P1)
|
||||
**Avoids:** Unmemoized chart data pitfall (use `useMemo` from the start), `chart.tsx` Recharts v3 patch (apply in Phase 1 before this phase begins)
|
||||
**Research flag:** Standard patterns — Recharts 3.8.0 chart implementations are fully documented. The specific `chart.tsx` fix is documented in issue #9892.
|
||||
### Phase 2: Preset Data, First-Run Detection, and DB Safety Constraints
|
||||
**Rationale:** Both the wizard and auto-budget creation depend on knowing whether this is a first-run user and on DB constraints that prevent duplicate data. Static data and detection hook have no UI dependencies and can be built and tested in isolation. The DB constraints must exist before any write mutations are triggered.
|
||||
**Delivers:** `src/data/presets.ts`, `src/hooks/useFirstRunState.ts`, DB migration for `UNIQUE (user_id, start_date)` on `budgets`, DB migration for `UNIQUE (user_id, name)` on `categories`, DB migration for `profiles.setup_completed` flag with backfill for v1.0 users.
|
||||
**Addresses:** Accurate first-run detection; protection against duplicate data at the DB layer
|
||||
**Avoids:** Pitfall 1 (duplicate budgets), Pitfall 6 (duplicate categories), Pitfall 8 (first-run gate triggers for existing users)
|
||||
**Research flag:** Standard pattern. The `setup_completed` backfill migration needs a SQL audit of the `profiles` table structure before writing — low-effort verification.
|
||||
|
||||
### Phase 3: Collapsible Dashboard Sections
|
||||
**Rationale:** `CategorySection` depends on `Collapsible` primitive (Phase 1) and `BudgetLineItems` (which reuses existing `InlineEditCell` atoms). This phase brings the dashboard to full feature completeness. Separating it from Phase 2 keeps each phase focused and ensures chart layout is stable before section collapse animations interact with chart resize behavior.
|
||||
**Delivers:** `CategorySection` components with Radix `Collapsible`, `BudgetLineItems` table, group totals row, variance indicators in section headers, carryover amount on balance card.
|
||||
**Addresses:** Collapsible sections with line items (P1), totals per section (table stakes), variance indicators (P2), carryover amount (P2)
|
||||
**Avoids:** Collapsible layout shift pitfall — use Radix `Collapsible` with CSS keyframe animation and `debounce={50}` on all `ResponsiveContainer` instances; never `display:none` toggle
|
||||
**Research flag:** Standard patterns — Radix Collapsible API is well-documented. The `--radix-collapsible-content-height` animation pattern is the established approach.
|
||||
### Phase 3: Setup Wizard
|
||||
**Rationale:** Depends on Phase 2 (presets data, first-run hook, DB constraints). The wizard is the core new-user experience. Building it after the data layer and constraints ensures the completion flow has correct idempotency guards from the start rather than retrofitting them later.
|
||||
**Delivers:** `/setup` route, `SetupWizardPage` (3 steps: income → items → review), wizard components, `WizardRoute` guard in `App.tsx`, localStorage state persistence, bilingual i18n keys for all wizard text.
|
||||
**Addresses:** Wizard-style first-run setup, pre-filled category items, skippable steps, running balance display
|
||||
**Avoids:** Pitfall 2 (wizard state lost on refresh) and Pitfall 6 (duplicate categories on re-run via idempotency guards)
|
||||
**Uses:** `react-hook-form` + `zod` + `@hookform/resolvers` (new dependencies), `checkbox` shadcn component
|
||||
**Research flag:** `react-hook-form` + `zod` integration is the standard shadcn/ui documented form pattern. Custom `WizardStepper` using shadcn primitives is a copy-paste block. No deeper research needed.
|
||||
|
||||
### Phase 4: Full-App Design Consistency
|
||||
**Rationale:** The dashboard establishes the design token application patterns. All other pages inherit from it. This phase is sequenced last because it depends on `PageShell` and the card/color patterns being proven on the dashboard first. FEATURES.md dependency graph makes this explicit: "all-pages redesign depends on dashboard being finished first."
|
||||
**Delivers:** `PageShell` applied to all 9 pages, consistent card/color/typography treatment on `BudgetDetailPage` (highest urgency — users navigate here directly from dashboard), `BudgetListPage`, `CategoriesPage`, `TemplatePage`, `LoginPage`, `RegisterPage`, `QuickAddPage`, `SettingsPage`. Empty state pattern for new months.
|
||||
**Addresses:** Consistent design language (table stakes), BudgetDetailPage polish (P1), remaining page polish (P2), empty states (P2)
|
||||
**Avoids:** i18n key regressions — switch to German locale and run key parity check before completing each sub-page
|
||||
**Research flag:** Standard patterns — `PageShell` wrapper is straightforward. The main risk is thoroughness (9 pages), not technical complexity.
|
||||
### Phase 4: Auto-Budget Creation
|
||||
**Rationale:** Depends on Phase 3 — a populated template must be possible before auto-creation is meaningful. Also depends on Phase 2 DB constraints being in place. The profile currency dependency must be resolved here, not deferred.
|
||||
**Delivers:** Auto-create `useEffect` in `DashboardPage` (with `useRef` guard), profile currency read (verify `profiles` table schema), upsert-based budget creation, first-creation toast notification via `sonner`.
|
||||
**Addresses:** Auto-created budget on first month visit, correct currency denomination for all users, silent creation for all subsequent months
|
||||
**Avoids:** Pitfall 1 (concurrent duplicate creation — DB constraint + ON CONFLICT guard) and Pitfall 5 (wrong currency — profile dependency resolved before mutation fires)
|
||||
**Research flag:** Verify the `profiles` table schema for the currency column name before writing the auto-create code. STACK.md flags this as needing confirmation. Low-effort: check `supabase/migrations/` directly.
|
||||
|
||||
### Phase 5: Inline Add-from-Library and Dashboard Simplification
|
||||
**Rationale:** Depends on Phase 4 — inline add is only meaningful when a budget exists for the current month. Dashboard simplification (removing the chart grid) is deferred until auto-creation is working so there is no regression window where the dashboard shows only empty state. Quick Add deprecation with redirect belongs in the same phase as the replacement being functional.
|
||||
**Delivers:** `AddOneOffSheet` component replacing `QuickAddPicker` at both call sites, removal of QuickAdd from sidebar nav, redirect from `/quick-add` to `/budgets`, removal of 3-column chart grid from `DashboardContent`, `scroll-area` shadcn component.
|
||||
**Addresses:** Inline add-from-library on budget view, Quick Add page consolidation, dashboard "at a glance" simplification, empty state for removed chart area
|
||||
**Avoids:** Pitfall 4 (Quick Add removal breaks nav/bookmarks — redirect added in same commit as nav removal)
|
||||
**Research flag:** Standard component replacement pattern. No deeper research needed.
|
||||
|
||||
### Phase Ordering Rationale
|
||||
|
||||
- **Foundation before features:** Pitfall 6 (design inconsistency) has a HIGH recovery cost. Establishing `index.css` tokens and shared components in Phase 1 prevents the most expensive failure mode.
|
||||
- **Dashboard before other pages:** FEATURES.md dependency graph is explicit — the dashboard establishes the patterns all pages inherit. Building it second (after foundation) lets Phase 4 apply proven patterns.
|
||||
- **Charts before collapsibles:** `ChartPanel` layout must be stable before collapsible sections are added beneath it. The ResizeObserver pitfall (Pitfall 3) is easiest to test and fix when charts are the only moving part.
|
||||
- **Sections in their own phase:** The collapsible + ResizeObserver interaction is the trickiest technical integration. Isolating it in Phase 3 limits blast radius if issues arise.
|
||||
- **Tokens first** because they are global-scope — any token change touches all pages. Establishing them before page work begins means every page built afterward is already on the correct visual foundation.
|
||||
- **Data + constraints before UI** because the wizard's correctness depends on DB-level deduplication and accurate first-run detection. Building the wizard UI first and adding guards later is the most common cause of data corruption in this pattern.
|
||||
- **Wizard before auto-budget** because auto-budget is only meaningful when there is a template to generate from. The wizard is the mechanism that creates the template. E2E testing of auto-budget requires a wizard-populated template.
|
||||
- **Auto-budget before inline add** because inline add requires a current-month budget to exist. The auto-creation flow provides that guarantee.
|
||||
- This ordering satisfies all 9 pitfall prevention phases documented in PITFALLS.md.
|
||||
|
||||
### Research Flags
|
||||
|
||||
Phases with standard, well-documented patterns (skip `/gsd:research-phase`):
|
||||
- **Phase 1:** Tailwind v4 `@theme inline`, OKLCH color tokens, and WCAG contrast requirements are all from official documentation with no ambiguity.
|
||||
- **Phase 2:** Recharts 3.8.0 chart implementations and the `chart.tsx` fix are fully documented. Month navigation via `useBudgets` hook is a straightforward state change in `DashboardContent`.
|
||||
- **Phase 3:** Radix Collapsible primitive is well-documented. The animation pattern with `--radix-collapsible-content-height` is the standard approach.
|
||||
- **Phase 4:** `PageShell` application and page-by-page refresh are repetitive pattern application, not novel implementation.
|
||||
Phases needing specific verification at planning time:
|
||||
- **Phase 4 (Auto-Budget Creation):** Verify the `profiles` table schema — specifically the `currency` column name and whether `useProfile` or `useAuth` is the correct hook to read it from. STACK.md flags this as a "verify in planning" item. Action: check `supabase/migrations/001_profiles.sql` before writing the auto-create spec.
|
||||
|
||||
No phases require pre-execution research. All major decisions are resolved by this research.
|
||||
|
||||
---
|
||||
Phases with standard patterns (skip research-phase):
|
||||
- **Phase 1:** Tailwind v4 `@theme inline` and OKLCH token overrides — fully documented, established pattern in this codebase.
|
||||
- **Phase 2:** Static data file, boolean flag migration, unique constraint migrations — no novel patterns.
|
||||
- **Phase 3:** `react-hook-form` + `zod` is the standard shadcn/ui form pattern; wizard stepper is a shadcn/ui blocks copy-paste.
|
||||
- **Phase 5:** Component replacement using existing hooks and shadcn Sheet — established pattern within this codebase.
|
||||
|
||||
## Confidence Assessment
|
||||
|
||||
| Area | Confidence | Notes |
|
||||
|------|------------|-------|
|
||||
| Stack | HIGH | Stack is locked and fully inspected. The one uncertainty (shadcn `chart.tsx` + Recharts v3 compatibility) has a documented fix in issue #9892. |
|
||||
| Features | HIGH | Grounded in competitor analysis (YNAB, Empower) and fintech UX standards. Feature prioritization is opinionated and defensible. |
|
||||
| Architecture | HIGH | Based on full codebase inspection. Component boundaries and build order are derived from actual file structure and import dependencies. |
|
||||
| Pitfalls | HIGH | Most pitfalls verified against official docs and open Recharts/shadcn issues. Recovery strategies and warning signs documented for each. |
|
||||
| Stack | HIGH | Verified against `package.json` and `supabase/migrations/`; actual installed versions confirmed; new dependencies verified via npm (April 2026); prior research's Recharts 3.x claim corrected |
|
||||
| Features | MEDIUM | Grounded in competitor analysis (YNAB, Monarch, EveryDollar, Quicken Simplifi) and UX onboarding literature; no first-party user testing data for this specific app's users |
|
||||
| Architecture | HIGH | Based on full codebase inspection; all hook names, mutation signatures, component locations, and file paths verified against source files |
|
||||
| Pitfalls | HIGH | Direct codebase analysis for each pitfall; React StrictMode double-invocation and TanStack Query mutation patterns are well-understood; DB constraint behaviors are standard PostgreSQL |
|
||||
|
||||
**Overall confidence: HIGH**
|
||||
**Overall confidence:** HIGH
|
||||
|
||||
### Gaps to Address
|
||||
|
||||
- **shadcn `chart.tsx` patch (issue #9892):** The `initialDimension` fix is community-verified but not yet merged into the official shadcn CLI output. Apply manually after generation and verify with a smoke test (render one chart, confirm no `width(-1)` warnings in console) before proceeding with Phase 2.
|
||||
- **WCAG contrast on category colors:** The recommended OKLCH values in STACK.md (chroma bumped to ~0.18+) have not been run through a contrast checker. During Phase 1, verify each category color pair against its background at the target luminance levels. Adjust chroma or lightness if any pair fails 3:1 (non-text) or 4.5:1 (text) thresholds.
|
||||
- **i18n key count baseline:** Before starting the overhaul, run `i18next-scanner` (or manually audit `en.json` vs `de.json`) to establish a baseline parity count. This makes regression detection in each subsequent phase mechanical rather than manual.
|
||||
- **`BudgetListPage` data shape:** Research did not inspect `BudgetListPage` implementation in detail. Phase 4 may uncover layout decisions that conflict with the dashboard's card pattern. Plan for one iteration pass on `BudgetListPage` specifically.
|
||||
- **`profiles` table currency column:** STACK.md's RPC SQL assumes a `currency` column on `profiles`. PITFALLS.md flags that auto-create defaults to EUR without reading it. Verify column name before Phase 4 begins — check `supabase/migrations/001_profiles.sql`. Low-effort, one-minute check.
|
||||
|
||||
---
|
||||
- **`setup_completed` backfill migration:** This migration must ship before or simultaneously with Phase 3 to prevent existing v1.0 users from hitting the wizard on their first v2.0 login. Write and test it in Phase 2; it is a prerequisite for Phase 3 deployment.
|
||||
|
||||
- **i18n for pre-filled wizard item names:** The ~15-20 preset items in `presets.ts` have English names (Rent, Groceries, Car Insurance, etc.). German translations must exist in `de.json` before the wizard ships. Define translation keys directly in `presets.ts` at data-definition time to make the i18n requirement explicit and auditable.
|
||||
|
||||
- **`quick_add_items` user data consideration:** Existing users may have data in `quick_add_items` that no longer surfaces in the UI after Phase 5. The new inline add uses `categories`, not `quick_add_items`. No migration is planned to bridge these. Acceptable risk for a personal/single-user app, but worth noting in user-facing release notes if the app has multiple users.
|
||||
|
||||
- **TanStack Query v5 `useEffect` mutation pattern:** PITFALLS.md recommends against firing mutations inside `useEffect` with data dependencies. ARCHITECTURE.md uses exactly this pattern (with a `useRef` guard). Verify the `useRef(false)` guard is sufficient for TanStack Query v5's mutation lifecycle — specifically that `mutate` called on an already-pending mutation is silently ignored (it is, per TQ v5 docs, but confirm in implementation).
|
||||
|
||||
## Sources
|
||||
|
||||
### Primary (HIGH confidence — official documentation)
|
||||
- [Recharts 3.0 Migration Guide](https://github.com/recharts/recharts/wiki/3.0-migration-guide) — v3 breaking changes, `Cell` deprecation, `blendStroke` removal
|
||||
- [Recharts API: ResponsiveContainer](https://recharts.github.io/en-US/api/ResponsiveContainer/) — `debounce` prop, dimension requirements
|
||||
- [shadcn/ui Chart Docs](https://ui.shadcn.com/docs/components/chart) — `ChartContainer`, `ChartConfig`, `ChartTooltipContent`
|
||||
- [shadcn/ui Accordion + Collapsible Docs](https://ui.shadcn.com/docs/components/radix/accordion) — component API, `type="multiple"`, independent state
|
||||
- [Radix UI Collapsible](https://www.radix-ui.com/primitives/docs/components/collapsible) — `--radix-collapsible-content-height` animation pattern
|
||||
- [Tailwind CSS v4 Theme Docs](https://tailwindcss.com/docs/theme) — `@theme inline`, CSS variable scoping, dark mode class strategy
|
||||
- [WCAG 2.1 SC 1.4.11 Non-text Contrast](https://www.w3.org/WAI/WCAG21/Understanding/non-text-contrast.html) — 3:1 minimum for UI components and chart elements
|
||||
- [WCAG SC 1.4.3 Contrast Minimum](https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html) — 4.5:1 for normal text
|
||||
- [React useMemo](https://react.dev/reference/react/useMemo) — memoization patterns for derived state
|
||||
- Existing codebase: full inspection of `src/pages/`, `src/components/`, `src/hooks/`, `src/lib/`, `src/index.css`
|
||||
### Primary (HIGH confidence)
|
||||
- `package.json` (project root) — authoritative installed versions; confirmed Recharts 2.15.4 not 3.x
|
||||
- `supabase/migrations/002_categories.sql` through `005_quick_add.sql` — authoritative schema
|
||||
- `src/App.tsx`, `src/components/AppLayout.tsx`, `src/pages/DashboardPage.tsx`, `src/pages/BudgetDetailPage.tsx` — confirmed existing routing, nav items, hook usage patterns
|
||||
- `src/hooks/useBudgets.ts`, `src/hooks/useTemplate.ts`, `src/hooks/useCategories.ts` — confirmed existing mutation signatures
|
||||
- `src/index.css`, `src/lib/palette.ts`, `src/lib/types.ts` — confirmed token structure and CSS variable names
|
||||
- npm search results (April 2026) — react-hook-form 7.72.0, zod 4.3.6, @hookform/resolvers 5.2.2
|
||||
- [shadcn/ui blocks page](https://ui.shadcn.com/blocks) — stepper patterns available as copy-paste blocks, no npm dependency
|
||||
|
||||
### Secondary (MEDIUM confidence — community sources, multiple corroborating)
|
||||
- [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 `initialDimension` fix for Recharts v3
|
||||
- [Recharts performance guide](https://recharts.github.io/en-US/guide/performance/) — memoization guidance
|
||||
- [Recharts ResizeObserver loop issue #1770](https://github.com/recharts/recharts/issues/1770) — confirmed bug and `debounce` workaround
|
||||
- [YNAB / Empower competitor analysis](https://bountisphere.com/blog/personal-finance-apps-2025-review) — feature comparison basis
|
||||
- [Fintech dashboard design best practices — Eleken, Merge Rocks, F9 Finance](https://merge.rocks/blog/fintech-dashboard-design-or-how-to-make-data-look-pretty) — visual design conventions
|
||||
- [shadcn/ui Charts examples](https://ui.shadcn.com/charts) — Donut with center text, bar chart patterns
|
||||
### Secondary (MEDIUM confidence)
|
||||
- YNAB, Monarch Money, EveryDollar, Quicken Simplifi — competitor feature patterns for wizard setup, auto-budget creation, and inline item adding
|
||||
- [zod.dev/v4](https://zod.dev/v4) — Zod 4 stable release notes and versioning strategy
|
||||
- [Evil Martians OKLCH guide](https://evilmartians.com/chronicles/better-dynamic-themes-in-tailwind-with-oklch-color-magic) — lightness/chroma values for pastel system design
|
||||
- UX onboarding literature (UX Design Institute, UXCam, UXDA, Smashing Magazine) — wizard step count drop-off data, sheet vs. modal UX rationale
|
||||
- [Recharts 3.0 migration guide](https://github.com/recharts/recharts/wiki/3.0-migration-guide) — confirmed breaking changes; basis for "do not upgrade" recommendation
|
||||
|
||||
### Tertiary (informing but not authoritative)
|
||||
- [Skeleton loading UX — LogRocket](https://blog.logrocket.com/ux-design/skeleton-loading-screen-design/) — skeleton mirrors real layout
|
||||
- [Empty state UX — Eleken](https://www.eleken.co/blog-posts/empty-state-ux) — CTA pattern for empty states
|
||||
- [Color theory in finance dashboards — Extej/Medium](https://medium.com/@extej/the-role-of-color-theory-in-finance-dashboard-design-d2942aec9fff) — palette chroma recommendations
|
||||
### Tertiary (LOW confidence — informing but not authoritative)
|
||||
- TanStack Query v5 Strict Mode double-invocation behavior — inferred from known React 18/19 `useEffect` patterns; verify against TQ v5 mutation docs if unexpected behavior appears during implementation
|
||||
- PostgreSQL `ON CONFLICT DO NOTHING` behavior on Supabase PostgREST layer — standard DB behavior but confirm the exact upsert syntax works via the `@supabase/supabase-js` v2 client
|
||||
|
||||
---
|
||||
|
||||
*Research completed: 2026-03-16*
|
||||
*Research completed: 2026-04-02*
|
||||
*Ready for roadmap: yes*
|
||||
|
||||
Reference in New Issue
Block a user