250 lines
10 KiB
Markdown
250 lines
10 KiB
Markdown
# Codebase Structure
|
|
|
|
**Analysis Date:** 2026-03-16
|
|
|
|
## Directory Layout
|
|
|
|
```
|
|
SimpleFinanceDash/
|
|
├── src/ # All application source code
|
|
│ ├── main.tsx # React 19 app entry point with providers
|
|
│ ├── App.tsx # Route configuration and guards
|
|
│ ├── index.css # Global Tailwind styles
|
|
│ ├── pages/ # Page components (routed views)
|
|
│ ├── components/ # Reusable and layout components
|
|
│ │ └── ui/ # Shadcn/Radix UI primitives (16 components)
|
|
│ ├── hooks/ # Custom data-fetching hooks (TanStack Query)
|
|
│ ├── lib/ # Utilities, types, configuration
|
|
│ └── i18n/ # Internationalization setup and resources
|
|
├── supabase/ # Supabase project files
|
|
│ └── migrations/ # Database schema migrations
|
|
├── public/ # Static assets
|
|
├── index.html # HTML entry point for Vite
|
|
├── package.json # Dependencies and build scripts
|
|
├── vite.config.ts # Vite bundler configuration
|
|
├── tsconfig.json # TypeScript base configuration
|
|
├── tsconfig.app.json # App-specific TypeScript config
|
|
├── tsconfig.node.json # Build script TypeScript config
|
|
├── eslint.config.js # ESLint configuration
|
|
├── components.json # Shadcn CLI component registry
|
|
├── .env.example # Example environment variables template
|
|
└── .gitignore # Git ignore rules
|
|
|
|
```
|
|
|
|
## Directory Purposes
|
|
|
|
**`src/pages/`:**
|
|
- Purpose: Page-level components that correspond to routes in App.tsx
|
|
- Contains: 9 page components (all .tsx)
|
|
- Key files:
|
|
- `DashboardPage.tsx` (316 lines) - Monthly budget dashboard with charts
|
|
- `BudgetDetailPage.tsx` (555 lines) - Detailed budget editing and item management
|
|
- `TemplatePage.tsx` (459 lines) - Monthly budget template editor
|
|
- `BudgetListPage.tsx` (261 lines) - List of all budgets with quick actions
|
|
- `CategoriesPage.tsx` (214 lines) - Category management (CRUD)
|
|
- `QuickAddPage.tsx` (202 lines) - Quick-add library editor
|
|
- `SettingsPage.tsx` (125 lines) - User preferences
|
|
- `LoginPage.tsx` (107 lines) - Email/password and OAuth login
|
|
- `RegisterPage.tsx` (81 lines) - User registration form
|
|
|
|
Each page follows pattern:
|
|
- Imports hooks at top
|
|
- Calls hooks in component body
|
|
- Renders UI from state
|
|
- Delegates complex logic to sub-components
|
|
|
|
**`src/components/`:**
|
|
- Purpose: Reusable UI components and layout wrappers
|
|
- Contains: Custom components + UI library primitives
|
|
- Key files:
|
|
- `AppLayout.tsx` - Sidebar wrapper for authenticated pages
|
|
- `QuickAddPicker.tsx` - Multi-modal quick-add workflow component
|
|
- `ui/` - 16 Shadcn-based components (Button, Dialog, Select, Table, etc.)
|
|
|
|
**`src/hooks/`:**
|
|
- Purpose: Encapsulate all server communication and state queries
|
|
- Contains: 6 custom hooks
|
|
- Key files:
|
|
- `useAuth.ts` - Session management and auth operations (signUp, signIn, signOut)
|
|
- `useBudgets.ts` - Budget CRUD, item management, template generation
|
|
- `useCategories.ts` - Category CRUD operations
|
|
- `useTemplate.ts` - Monthly budget template management
|
|
- `useQuickAdd.ts` - Quick-add item library CRUD
|
|
- `use-mobile.ts` - Responsive breakpoint detection utility
|
|
|
|
Each hook:
|
|
- Defines typed query keys as const arrays
|
|
- Initializes useQuery/useMutation from TanStack Query
|
|
- Returns { data, loading, ...mutations }
|
|
- Implements onSuccess cache invalidation
|
|
|
|
**`src/lib/`:**
|
|
- Purpose: Core utilities, types, and configuration
|
|
- Contains: 5 files
|
|
- Key files:
|
|
- `types.ts` - TypeScript interfaces: Profile, Category, Budget, BudgetItem, Template, TemplateItem, QuickAddItem
|
|
- `supabase.ts` - Supabase client creation with environment validation
|
|
- `palette.ts` - Category color constants (CSS variables) and labels (en/de)
|
|
- `format.ts` - Currency formatting with Intl.NumberFormat API
|
|
- `utils.ts` - General helpers (like cn for class merging)
|
|
|
|
**`src/i18n/`:**
|
|
- Purpose: Internationalization setup and resource files
|
|
- Contains: `index.ts` and JSON translation files
|
|
- Key files:
|
|
- `index.ts` - i18next initialization with react-i18next bindings
|
|
- `en.json` - English translation strings (namespaced by feature)
|
|
- `de.json` - German translation strings
|
|
- Initialized at app startup before any React render
|
|
- Provides `useTranslation()` hook for all components
|
|
|
|
**`src/components/ui/`:**
|
|
- Purpose: Unstyled, accessible UI primitives from Shadcn and Radix UI
|
|
- Contains: 16 files of component exports
|
|
- Includes: Badge, Button, Card, Dialog, Dropdown Menu, Input, Label, Popover, Select, Separator, Sheet, Sidebar, Skeleton, Table, Tooltip, Sonner Toast wrapper
|
|
- Pattern: Each wraps Radix primitive with Tailwind styling
|
|
- Do NOT modify these files — regenerate via Shadcn CLI if needed
|
|
|
|
## Key File Locations
|
|
|
|
**Entry Points:**
|
|
- `src/main.tsx` - DOM mount point, providers initialization
|
|
- `src/App.tsx` - Route definitions and authentication guards
|
|
- `index.html` - Vite HTML template with root div
|
|
|
|
**Configuration:**
|
|
- `vite.config.ts` - Build tooling (React plugin, Tailwind vite plugin, @ alias)
|
|
- `tsconfig.json` - Base TS config with @ path alias
|
|
- `eslint.config.js` - Linting rules
|
|
- `components.json` - Shadcn CLI registry
|
|
- `package.json` - Dependencies: react@19, react-router-dom@7, @tanstack/react-query@5, @supabase/supabase-js@2, i18next, lucide-react, recharts, tailwindcss@4, sonner
|
|
|
|
**Core Logic:**
|
|
- `src/hooks/useBudgets.ts` - Largest hook (369 lines) with factory pattern for detail queries
|
|
- `src/hooks/useTemplate.ts` - Template mutations with sort_order management
|
|
- `src/lib/types.ts` - Single source of truth for domain types
|
|
- `src/lib/supabase.ts` - Client configuration (2 lines of config + validation)
|
|
|
|
**Testing:**
|
|
- No test files present (no `*.test.ts`, `*.spec.ts`)
|
|
- No jest.config.js or vitest.config.ts
|
|
|
|
## Naming Conventions
|
|
|
|
**Files:**
|
|
- Pages: PascalCase with "Page" suffix (`DashboardPage.tsx`)
|
|
- Hooks: camelCase with "use" prefix (`useAuth.ts`, `useBudgets.ts`)
|
|
- Components: PascalCase (`AppLayout.tsx`, `QuickAddPicker.tsx`)
|
|
- Utilities: camelCase descriptive (`format.ts`, `palette.ts`)
|
|
- Types: camelCase file, PascalCase exports (`types.ts` exports `interface Budget`)
|
|
- UI components: kebab-case file, PascalCase export (`card.tsx` exports `Card`)
|
|
|
|
**Directories:**
|
|
- Feature folders: lowercase plural (`src/hooks/`, `src/pages/`, `src/components/`)
|
|
- UI library: `ui/` subfolder under components
|
|
|
|
**Functions & Variables:**
|
|
- Functions: camelCase (`formatCurrency`, `useBudgets`)
|
|
- Component functions: PascalCase (`DashboardPage`, `QuickAddPicker`)
|
|
- Constants: UPPER_SNAKE_CASE (`CATEGORY_TYPES`, `EXPENSE_TYPES`)
|
|
- Variables: camelCase (`budgetId`, `categoryId`, `isSaving`)
|
|
|
|
**Types:**
|
|
- Interfaces: PascalCase (`Budget`, `BudgetItem`)
|
|
- Type unions: PascalCase (`CategoryType`)
|
|
- Props interfaces: PascalCase ending with "Props" (`QuickAddPickerProps`)
|
|
|
|
## Where to Add New Code
|
|
|
|
**New Feature (e.g., Reports):**
|
|
1. Create page: `src/pages/ReportsPage.tsx`
|
|
2. Create hook: `src/hooks/useReports.ts` with query keys and mutations
|
|
3. Add types: `src/lib/types.ts` - add new interfaces (Report, ReportItem)
|
|
4. Add route: `src/App.tsx` - add Route element
|
|
5. Add nav link: `src/components/AppLayout.tsx` - add to navItems array
|
|
6. Add i18n: `src/i18n/en.json` and `src/i18n/de.json` - add new keys
|
|
|
|
**New Component (e.g., CategoryBadge):**
|
|
- If simple display component: `src/components/CategoryBadge.tsx`
|
|
- If UI primitive wrapper: `src/components/ui/category-badge.tsx` (follow shadcn pattern)
|
|
- Composition: Import from ui/ folder, layer styling via className
|
|
|
|
**New Utility Function:**
|
|
- General helpers: `src/lib/utils.ts`
|
|
- Domain-specific (e.g., budget math): Add to relevant hook file or create `src/lib/budgetHelpers.ts`
|
|
- Formatting logic: `src/lib/format.ts`
|
|
|
|
**New Hook:**
|
|
- Data fetching: `src/hooks/useFeatureName.ts`
|
|
- Pattern: Export named function, define query keys, use useQuery/useMutation, return typed object
|
|
- Example structure from `useTemplate.ts`:
|
|
- Query keys at top (const)
|
|
- Helper functions (async functions)
|
|
- Main hook function with useQuery/useMutation setup
|
|
- Exposed API object return
|
|
|
|
**Styling:**
|
|
- Component styles: Tailwind className in JSX (no CSS files)
|
|
- Global styles: `src/index.css` (imports Tailwind directives)
|
|
- Color system: CSS variables in theme (Tailwind config)
|
|
- Category colors: `src/lib/palette.ts` (maps to CSS var(--color-X))
|
|
|
|
## Special Directories
|
|
|
|
**`src/components/ui/`:**
|
|
- Purpose: Shadcn registry of unstyled, accessible Radix UI components
|
|
- Generated: Via `npx shadcn-ui@latest add [component]`
|
|
- Committed: Yes (production code)
|
|
- Do NOT hand-edit — regenerate if Shadcn updates
|
|
|
|
**`public/`:**
|
|
- Purpose: Static assets (favicon, images, fonts)
|
|
- Generated: No
|
|
- Committed: Yes
|
|
- Served at root by Vite
|
|
|
|
**`supabase/migrations/`:**
|
|
- Purpose: Database schema as versioned SQL files
|
|
- Generated: Via Supabase CLI
|
|
- Committed: Yes (tracked via git)
|
|
- Applied: By `supabase db push` command
|
|
|
|
**`.env` files:**
|
|
- Purpose: Runtime configuration (Supabase URL, API key)
|
|
- Generated: Via `.env.example` template
|
|
- Committed: NO — in .gitignore
|
|
- Required for: Local dev and CI/CD
|
|
|
|
**`dist/`:**
|
|
- Purpose: Production bundle output
|
|
- Generated: Via `npm run build`
|
|
- Committed: No — in .gitignore
|
|
- Deployment: Upload contents to CDN or web server
|
|
|
|
## Code Organization Principles
|
|
|
|
**Vertical Slices:**
|
|
- Feature → Page → Hook → Library
|
|
- Minimizes cross-feature coupling
|
|
- Easy to add/remove features
|
|
|
|
**Co-location of Related Code:**
|
|
- Page component near its hooks
|
|
- Query keys defined in same hook as queries
|
|
- Mutations and queries in same hook for domain entity
|
|
|
|
**Type Safety:**
|
|
- All Supabase queries cast return value to TypeScript type
|
|
- TanStack Query generic parameters: `useQuery<Type>()` and `useMutation<Payload, Response>()`
|
|
- Props interfaces for all custom components
|
|
|
|
**Consistent Hook Patterns:**
|
|
- All data hooks follow: query setup → mutations setup → return typed object
|
|
- Mutations always have onSuccess cache invalidation
|
|
- Query keys are hierarchical arrays enabling granular invalidation
|
|
|
|
---
|
|
|
|
*Structure analysis: 2026-03-16*
|