Skip to main content

System Architecture

The André Ruperto Portfolio is a full-stack web application built with a modern tech stack:
┌─────────────────────────────────────────────────────────────┐
│                         Client Layer                         │
│  React 18 + TypeScript + Vite + TailwindCSS + Tanstack Query│
└────────────────────────┬────────────────────────────────────┘

                         │ HTTP/REST

┌────────────────────────▼────────────────────────────────────┐
│                      Backend Layer                           │
│              Express 4 + Node.js + TypeScript                │
│  ┌─────────────┐  ┌──────────────┐  ┌──────────────┐       │
│  │   Auth      │  │   Projects   │  │   Contact    │       │
│  │ Middleware  │  │   Routes     │  │   Routes     │       │
│  └─────────────┘  └──────────────┘  └──────────────┘       │
└────────────────────────┬────────────────────────────────────┘

           ┌─────────────┼─────────────┐
           │             │             │
┌──────────▼──────┐  ┌──▼────────┐  ┌▼─────────────┐
│   PostgreSQL    │  │  Resend   │  │    Static    │
│   + Prisma      │  │   Email   │  │    Assets    │
└─────────────────┘  └───────────┘  └──────────────┘

Request Flow

1. Page Load Flow

1. User requests https://andreruperto.dev/
2. Express serves static index.html from backend/dist/
3. Browser loads React bundle and initializes app
4. React Router renders Index page
5. Components mount and fetch data from /api/projects
6. Backend queries PostgreSQL via Prisma
7. JSON response rendered in UI

2. Contact Form Submission Flow

1. User fills contact form (ContactSection component)
2. React Hook Form validates with Zod schema
3. POST /api/contact with rate limiting (5 requests/hour)
4. Backend validates: email format, required fields, length limits
5. Resend API sends notification email to André
6. Resend API sends confirmation email to user
7. Success response displayed via Sonner toast

3. Admin Authentication Flow

1. Admin navigates to /admin/login
2. AdminLogin page renders with password form
3. POST /api/auth/login with rate limiting (5 attempts/15 min)
4. Backend validates password against ADMIN_PASSWORD env var
5. JWT token generated (24h expiry) using JWT_SECRET
6. Token stored in client and sent in Authorization header
7. Protected routes verify token via authMiddleware

Technology Stack

  • Framework: React 18.3.1 with TypeScript
  • Build Tool: Vite 5.4.19
  • Routing: React Router DOM 6.30.1
  • State Management: Tanstack Query 5.83.0
  • Forms: React Hook Form 7.61.1 + Zod 3.25.76
  • UI Components: Radix UI primitives
  • Styling: TailwindCSS 3.4.17 + class-variance-authority
  • Icons: Lucide React 0.462.0
  • Notifications: Sonner 1.7.4

Environment Configuration

The application uses different .env files based on NODE_ENV:
// backend/src/server.js:12-14
const envFile = process.env.NODE_ENV === 'production' 
  ? '.env.production' 
  : '.env';
dotenv.config({ path: envFile });

Required Environment Variables

  • DATABASE_URL - PostgreSQL connection string
  • RESEND_API_KEY - Email service API key
  • ADMIN_PASSWORD - Admin authentication password
  • JWT_SECRET - Token signing secret
  • PORT - Backend server port (default: 3001)
  • VITE_API_URL - API endpoint for frontend (default: /api)

Development vs Production

Security Features

  1. Rate Limiting
    • Login: 5 attempts per 15 minutes
    • Contact form: 5 submissions per hour
  2. Input Validation
    • Email format validation
    • Field length limits (name: 100, subject: 200, message: 5000)
    • HTML escaping for email templates
  3. Authentication
    • JWT tokens with 24-hour expiry
    • Authorization header or query token support
    • Password-based admin access
  4. CORS
    • Configured for cross-origin requests
    • JSON body size limit: 1MB

File Structure

~/workspace/source/
├── src/                    # Frontend React application
│   ├── components/         # React components
│   ├── pages/             # Route pages
│   ├── hooks/             # Custom React hooks
│   ├── lib/               # Utilities
│   └── assets/            # Static assets
├── backend/
│   ├── src/
│   │   └── server.js      # Express server
│   ├── prisma/
│   │   └── schema.prisma  # Database schema
│   └── scripts/
│       └── seed.ts        # Database seeding
├── public/                # Public static files
└── scripts/
    └── copy-images.js     # Build script

Next Steps

Frontend Architecture

Learn about React components, routing, and state management

Backend Architecture

Explore Express routes, middleware, and API endpoints

Database Schema

Understand Prisma models and database structure

API Reference

View complete API endpoint documentation

Build docs developers (and LLMs) love