Skip to content

feat: investment portfolio with Supabase auth, multi-asset tracking, and projections - #4

Merged
Gaells merged 4 commits into
masterfrom
feat/ui-ux-improvements
Oct 4, 2026
Merged

Gaells merged 4 commits into
masterfrom
feat/ui-ux-improvements

Conversation

@Gaells

@Gaells Gaells commented Oct 4, 2026

Copy link
Copy Markdown
Owner

Transforms FinForge from a calculator suite into a full investment portfolio app with auth, persistence, and projections.

What's new

Backend & Infrastructure

  • Supabase setup with @supabase/supabase-js + @supabase/ssr
  • SQL migration with 5 tables + RLS + auto-profile trigger on signup
  • Server-side cookie middleware for session refresh

Authentication

  • /login, /signup, logout via Server Actions
  • useAuth hook + UserMenu dropdown with avatar
  • Email validation, password min length, helpful error messages

Domain & Services (39 new Vitest tests, 116 total passing)

  • portfolio.service — average cost, P&L realized/unrealized, partial sells
  • fixedIncome.service — CDI%, IPCA+, prefixado, maturity
  • projection.service — month-by-month with contributions/withdrawals/IPCA
  • allocation.service — diversification + concentration alerts (>20%)
  • dividends.service — yield on cost, by month / by asset
  • priceFetcher.service — CoinGecko + Brapi + Yahoo + AwesomeAPI with 15min cache
  • currency.service — BRL ↔ USD with USDBRL rate from cache

UI & Routes

  • /portfolio with sub-pages: holdings, allocation, projection, simulator, settings
  • /assets (list) + /assets/new + /assets/[id] (view/edit/delete)
  • /transactions (list) + /transactions/new
  • Shared PortfolioShell with sidebar + mobile tabs
  • AssetForm with 6 types including fixed income details
  • TransactionForm with 4 transaction types (BUY/SELL/DIVIDEND/INCOME)
  • Refresh prices button + /api/prices/refresh route
  • Backup/Restore via JSON (settings page)

UI fixes bundled

  • Completed Tailwind v4 @theme inline color mapping (popover, accent, muted, secondary, destructive, border, input, ring, sidebar)
  • Fixed Select dropdown transparency (inline style fallback)
  • Fixed Recharts in server components (extracted to client components)
  • Fixed Supabase middleware return type
  • Fixed native <select> bg-transparent issues across forms

Setup

  1. Create Supabase project, run supabase/migrations/20251003000000_init.sql in SQL Editor
  2. Disable email confirmation for testing (Auth → Providers → Email)
  3. Copy URL + Publishable key to .env.local
  4. npm install && npm run dev

Tests

npm test         # 116/116 passing
npm run type-check
npm run lint

…ng, and projections

Transform FinForge from a calculator suite into a full investment portfolio app.

Backend & Infrastructure
- Add Supabase setup (@supabase/supabase-js, @supabase/ssr)
- Create SQL migration with 5 tables (profiles, assets, fixed_income_details,
  transactions, price_cache) + RLS policies + auto-profile trigger
- Add supabase/migrations/20251003000000_init.sql

Authentication
- Login/signup/logout pages with Server Actions
- useAuth hook and UserMenu component
- Middleware for session refresh

Domain & Services (with 39 new Vitest tests)
- portfolio.service: average cost, realized/unrealized P&L, partial sells
- fixedIncome.service: CDI%, IPCA+, prefixado, maturity
- projection.service: month-by-month with contribution/withdrawal/IPCA
- allocation.service: diversification + concentration warnings
- dividends.service: yield on cost, by month/by asset
- priceFetcher.service: CoinGecko + Brapi + Yahoo Finance + AwesomeAPI
  with 15min cache in price_cache table
- currency.service + portfolio-aggregator: BRL+USD aggregation

Routes & UI
- /login, /signup
- /portfolio with sub-pages: holdings, allocation, projection,
  simulator, dividends, settings
- /assets CRUD (stock/etf/fii/crypto/fixed_income/cash)
- /transactions CRUD (buy/sell/dividend/income)
- Shared PortfolioShell with sidebar + mobile tabs
- AssetForm with 6 asset types including FI details
- TransactionForm with 4 transaction types
- RefreshPricesButton + /api/prices/refresh route
- Backup/Restore JSON (export/import)
- PortfolioTeaser on dashboard for logged-in users

Calculator suite preserved and accessible from dashboard.

UI fixes
- Complete Tailwind v4 @theme color mapping (popover, accent, muted,
  secondary, destructive, border, input, ring, sidebar)
- Fix Select component transparency with inline style fallback
- Fix Recharts in server components (extract to client components)
- Fix Supabase middleware to return Response not object
- Fix native select bg-transparent across forms
@vercel

vercel Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
finforge Ready Ready Preview, v0 Oct 4, 2026 2:12am UTC

Vercel build failed with 'Super expression must either be null or function'
on /portfolio/allocation because AllocationView.tsx used recharts (class
components with browser dependencies) without 'use client' directive.

Add 'use client' to AllocationView.tsx. Other recharts components
(ProjectionPanel, Simulator, DividendsChart) already had it.
During Vercel build, the Supabase middleware was called for static page
prerendering (/compound-interest, /fire-calculator, etc.) and threw
'Your project's URL and API key are required to create a Supabase client!'
when env vars weren't configured in Vercel project settings.

Make middleware gracefully skip auth refresh when env vars are missing,
and wrap getUser() in try/catch to avoid breaking builds on network errors.

Pages still work:
- Public calculators: don't need auth, render normally
- Protected portfolio pages: redirect via layout-level server checks
…v vars

Vercel preview deployments and local builds without .env.local were
failing prerender with:
  'Your project's URL and API key are required to create a Supabase client!'

Even pages like /transactions that don't use Supabase auth were failing
because Next.js evaluates module graph for page data collection, and
the UserMenu (used in CalculatorLayout header) calls useAuth which
creates a browser client.

Fix:
- createClient in client.ts and server.ts now return a stub proxy
  when env vars are missing instead of throwing
- Proxy chains .from().select().order().limit() and resolves with
  { data: null, error: { message: 'Supabase env vars ausentes' } }
  for any await
- Auth methods return error responses

Pages render without Supabase data when env vars are absent (which is
fine for builds/preview), and work normally when env vars are present.
@Gaells
Gaells merged commit 0e8f32a into master Oct 4, 2026
8 checks passed

This branch was successfully deployed

1 active deployment
Preview — 2587f6cc Deployed Oct 4, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant