v1.9.3 · Released · March 28, 2026
Architecture Improvements & Multi-Currency Invoice Fix
Major internal refactor: error boundaries, Suspense streaming dashboard, server-side pagination for income/expense, tag-based cache revalidation, extracted UserService/AuthService/CronLogService, standardized controller patterns, useServerAction hook, and fixed invoice summary currency mixing.
Error Handling
- Error Boundaries: Added global-error.tsx, app error.tsx, and authenticated error.tsx to catch and display errors gracefully instead of blank screens.
- Not Found Pages: Added custom 404 pages for both public and authenticated routes with contextual navigation links.
Dashboard Streaming
- Suspense Boundaries: Dashboard broken into 5 independently streaming sections (KPI Cards, Budget Health, Goals, Invoices, Transactions & Accounts).
- Skeleton Loading: Each section shows a tailored skeleton while its data loads, instead of blocking the entire page.
- Page Reduction: Dashboard page went from 600+ lines to ~56 lines of clean Suspense composition.
Income & Expense Pagination
- Server-Side Pagination: Income and expense pages now use server-side pagination (20 per page) with sortable columns, matching the work entries pattern.
- Month-Scoped Navigation: Browse by month/year with lightweight monthly totals grid for quick overview.
Invoice Multi-Currency Fix
- Currency-Aware Summaries: Invoice summary cards now group totals by currency instead of mixing USD + EUR into one number.
- Per-Currency Display: Outstanding and Total Paid cards show each currency on its own line when multiple currencies exist.
- Dashboard Widget: Invoice dashboard widget updated to handle multi-currency outstanding amounts.
Architecture Standardization
- Tag-Based Revalidation: All 16 controllers migrated from revalidatePath('/', 'layout') to targeted revalidateTag() with domain-specific cache tags.
- Shared Auth Guard: Extracted getAuthenticatedUser() from 14 controllers into a single server/lib/auth-guard.ts.
- UserService: Consolidated 15+ scattered prisma.user.* queries across pages, controllers, and services into server/modules/user/user.service.ts with 17 methods.
- AuthService: Extracted registration, password reset, and token management from server/actions/auth.ts into server/modules/auth/auth.service.ts.
- CronLogService: Deduplicated cron audit logging across 5 cron routes into server/modules/cron/cron.service.ts.
- Controller Input Standardization: 6 controllers (11 actions) migrated from FormData parsing to (data: unknown) + Zod safeParse.
- Unified Return Types: All 19 controllers standardized to ActionResponse<T> = { success: true; data?: T } | { error: string }.
- Notification Logic: Moved notification dispatch and budget alert logic from income/expense controllers into their respective services.
- useTransition Standardization: 9 form components migrated from manual useState pending state to React useTransition.
- useServerAction Hook: New hook for simple mutations (delete, archive, status toggle) eliminating repeated pending/toast boilerplate.
- Simplified Serialization: serialize() utility reduced from 2-pass to single-pass with identical output.
- Dev Dependencies: 13 build-only packages moved from dependencies to devDependencies for smaller production images.