Skip to main content

Overview

BudgetView is built using a modern full-stack architecture with Next.js (App Router) on the frontend and Supabase (PostgreSQL) as the backend-as-a-service platform. The application follows a serverless architecture pattern with client-side rendering and real-time database synchronization.

Technology Stack

Frontend Framework

Next.js 16.0

React-based full-stack framework with App Router for modern routing and server components

React 19.2

Latest React version with concurrent features and improved performance

TypeScript 5.x

Static typing for enhanced code quality and developer experience

Tailwind CSS 4.x

Utility-first CSS framework for rapid UI development

Backend & Database

Supabase

PostgreSQL-based BaaS providing authentication, real-time subscriptions, and RESTful APIs

Node.js 25.x

Runtime environment for Next.js server-side operations

Key Dependencies

The application leverages several production-ready libraries:
package.json
{
  "dependencies": {
    "@supabase/supabase-js": "^2.81.1",
    "@radix-ui/react-dialog": "^1.1.15",
    "@radix-ui/react-dropdown-menu": "^2.1.16",
    "@radix-ui/react-select": "^2.0.0",
    "date-fns": "^4.1.0",
    "jspdf": "^3.0.4",
    "lucide-react": "^0.553.0",
    "recharts": "^3.4.1",
    "react-day-picker": "^9.11.3"
  }
}

Architecture Diagram

The following diagram illustrates how different components interact:

Application Layers

1. Presentation Layer

The presentation layer is built with React Server Components and Client Components:
  • Page layouts (app/*/layout.tsx)
  • Static content rendering
  • Initial data fetching
Key UI Components:
  • Radix UI primitives for accessibility
  • Custom components in /components/ui/
  • Form validation with client-side logic

2. Data Access Layer

Supabase client initialization:
lib/supabaseClient.ts
import { createClient } from '@supabase/supabase-js'

const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!
const supabaseKey = process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!

export const supabase = createClient(supabaseUrl, supabaseKey)
All database operations use the Supabase JavaScript client with TypeScript types:
// Example: Fetching wallets with transactions
const { data: walletRows, error } = await supabase
  .from("billeteras")
  .select("id, nombre")
  .order("nombre", { ascending: true })

if (error) throw error

3. Business Logic Layer

Business logic is implemented within React components using custom hooks:

Data Flow Patterns

Create Operation

1

User submits form

Client-side validation ensures data integrity before submission
2

Authenticate user

Retrieve current user session from Supabase Auth
const { data: { user } } = await supabase.auth.getUser()
if (!user) throw new Error("Not authenticated")
3

Insert into database

Supabase client sends INSERT request with user_id
const { error } = await supabase
  .from("transacciones")
  .insert({
    monto: parsedAmount,
    tipo: "gasto",
    categoria_id: categoryId,
    usuario_id: user.id,
    billetera_id: walletId,
    fecha_transaccion: new Date().toISOString()
  })
4

RLS verification

PostgreSQL Row Level Security policies verify ownership
5

Update UI

Refresh data and broadcast update events
await loadData()
window.dispatchEvent(new CustomEvent("transactions:updated"))

Read Operation

1

Query with filters

Apply user-specific filters and date ranges
2

Join related data

Use Supabase’s query builder to join tables
.select("id, monto, tipo, categorias(id, nombre, tipo)")
3

Transform data

Convert database rows to TypeScript types
4

Render components

React components display formatted data

State Management

BudgetView uses React’s built-in state management:
  • useState for component-level state
  • useEffect for side effects and data fetching
  • useCallback for memoized functions
  • useMemo for computed values
  • Custom events for cross-component communication
Event-driven updates:
// Broadcasting wallet updates
window.dispatchEvent(new CustomEvent("wallets:updated"))

// Listening for updates
window.addEventListener("wallets:updated", handleUpdate)

Security Architecture

Security is enforced at multiple layers to ensure data protection.

Authentication Flow

  1. User login → Supabase Auth validates credentials
  2. JWT issued → Access token stored in browser
  3. API requests → Token sent with every request
  4. RLS enforcement → PostgreSQL validates user ownership

Environment Variables

Sensitive configuration is stored in environment variables:
.env.local
NEXT_PUBLIC_SUPABASE_URL=your_project_url
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=your_anon_key
Never commit .env.local to version control. Use .env.example for templates.

Performance Optimizations

Code Splitting

Next.js automatically splits code by route for faster initial loads

React Memoization

useMemo and useCallback prevent unnecessary re-renders

Parallel Data Fetching

Promise.all() loads multiple resources simultaneously

Abort Controllers

Cancel in-flight requests when components unmount

Deployment Architecture

The application is designed for deployment on modern hosting platforms:
  • Vercel (recommended): Automatic deployments from Git
  • Netlify: Alternative static hosting platform
  • Self-hosted: Docker containers with Node.js runtime
Build process:
npm run build  # Creates optimized production build
npm start      # Starts production server on port 3000

Real-time Capabilities

While not currently implemented, Supabase provides real-time subscriptions:
// Future enhancement: real-time transaction updates
const subscription = supabase
  .channel('transactions')
  .on('postgres_changes', 
    { event: 'INSERT', schema: 'public', table: 'transacciones' },
    (payload) => console.log('New transaction:', payload)
  )
  .subscribe()

Scalability Considerations

The current architecture supports growth to thousands of concurrent users without major refactoring.
  • Serverless functions: Scales automatically with traffic
  • Connection pooling: Supabase handles database connections efficiently
  • CDN distribution: Static assets served from edge locations
  • Indexed queries: Database indexes optimize query performance

Technology Justification

Each technology was chosen for specific reasons:
TechnologyJustification
Next.jsIndustry-standard React framework with excellent DX, SEO, and performance
TypeScriptPrevents runtime errors in financial calculations through static typing
SupabasePostgreSQL reliability with modern API, built-in auth, and real-time capabilities
Tailwind CSSRapid development with utility classes, small bundle size, and maintainability
Radix UIAccessible, unstyled components that meet WCAG standards

For implementation details, see the Database Schema and Authentication pages.

Build docs developers (and LLMs) love