184 lines
20 KiB
Markdown
184 lines
20 KiB
Markdown
# Project Research Summary
|
|
|
|
**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
|
|
|
|
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 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 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 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 (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
|
|
|
|
**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
|
|
|
|
**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)
|
|
|
|
**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 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 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)
|
|
|
|
**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
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
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 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 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: 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: 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: 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
|
|
|
|
- **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 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.
|
|
|
|
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 | 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
|
|
|
|
### Gaps to Address
|
|
|
|
- **`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)
|
|
- `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)
|
|
- 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 (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-04-02*
|
|
*Ready for roadmap: yes*
|