Files
kilo-cv/docs/architecture.md
Tuan-Dat Tran 8d7000eb31
Some checks failed
Release / Build & Push Docker Image (push) Has been cancelled
Release / Release (push) Has been cancelled
docs: add architecture documentation
- Document frontend and backend tech stacks
- Describe component hierarchy and routing
- Explain state management with React Context
- Document API endpoints and database schema
- Include authentication modes (simple/Keycloak)
- Describe design patterns used
- Document testing architecture
2026-02-23 22:46:46 +01:00

13 KiB

Architecture Documentation

Overview

kilo-cv is a full-stack web application for managing and displaying a professional CV/resume. It features a public-facing CV display page and an authenticated admin panel for content management.

Key Features

  • Public CV Display: Responsive, animated CV page with sections for experience, skills, education, and projects
  • Admin Panel: Authenticated interface for editing CV content
  • REST API: Backend API for data management
  • Export/Import: JSON export and import functionality
  • API Documentation: Interactive Swagger UI

Technology Stack

Frontend

Technology Version Purpose
React 19.x UI library
Vite 7.x Build tool and dev server
Tailwind CSS 4.x Styling
Framer Motion 12.x Animations
Lucide React 0.574.x Icon library
React Router DOM 7.x Client-side routing

Backend

Technology Version Purpose
Express.js 4.x REST API server
Knex.js 3.x SQL query builder
better-sqlite3 11.x SQLite database driver
swagger-jsdoc 6.x OpenAPI documentation generation
swagger-ui-express 5.x Swagger UI serving

Directory Structure

kilo-cv/
├── src/                          # Frontend source
│   ├── components/               # Public CV display components
│   │   ├── Hero.jsx             # Name, title, introduction
│   │   ├── Experience.jsx       # Work history section
│   │   ├── Skills.jsx           # Skills by category
│   │   ├── Education.jsx        # Education history
│   │   ├── Projects.jsx         # Project showcase
│   │   └── Contact.jsx          # Contact information
│   ├── admin/                    # Admin panel
│   │   ├── AdminLayout.jsx      # Admin layout with navigation
│   │   ├── AdminPersonal.jsx    # Personal info editor
│   │   ├── AdminExperience.jsx  # Experience editor
│   │   ├── AdminSkills.jsx      # Skills editor
│   │   ├── AdminEducation.jsx   # Education editor
│   │   ├── AdminProjects.jsx    # Projects editor
│   │   ├── pages/
│   │   │   └── LoginPage.jsx    # Authentication page
│   │   ├── sections/            # Reusable form components
│   │   │   ├── PersonalForm.jsx
│   │   │   ├── ExperienceForm.jsx
│   │   │   ├── SkillsForm.jsx
│   │   │   ├── EducationForm.jsx
│   │   │   └── ProjectsForm.jsx
│   │   ├── hooks/               # React contexts and custom hooks
│   │   │   ├── CVContext.jsx    # CV data state management
│   │   │   ├── AuthContext.jsx  # Authentication state
│   │   │   ├── useCVData.js     # CV data access hook
│   │   │   └── useFormValidation.js
│   │   └── components/
│   │       └── ExportButton.jsx
│   ├── lib/                      # Utilities and API client
│   │   ├── api.js               # API client functions
│   │   ├── auth.js              # Token management
│   │   ├── cv-data.js           # CV validation utilities
│   │   └── cv.json              # Default CV data structure
│   ├── data/
│   │   └── cv.js
│   ├── App.jsx                   # Root component with routing
│   ├── main.jsx                  # React entry point
│   └── index.css                 # Global styles (Tailwind)
├── backend/                      # Backend source
│   ├── routes/                   # API route handlers
│   │   ├── cv.js                # CV CRUD endpoints
│   │   ├── auth.js              # Authentication endpoints
│   │   └── docs.js              # Swagger documentation route
│   ├── db/
│   │   └── init.js              # Database initialization
│   ├── migrations/
│   │   └── 20260220000001_initial_schema.js
│   ├── middleware/
│   │   └── auth.js              # JWT authentication middleware
│   ├── seeds/
│   │   └── initial_cv_data.js   # Initial data seeding
│   ├── __tests__/
│   │   └── api.test.js          # API tests
│   ├── server.js                 # Express server entry point
│   └── knexfile.js               # Knex configuration
├── tests/                        # Test suites
│   ├── e2e/                      # Playwright E2E tests
│   ├── integration/              # Integration tests
│   ├── regression/               # Snapshot/regression tests
│   └── performance/              # k6 and Lighthouse tests
├── docs/                         # Documentation
├── public/                       # Static assets
└── .github/                      # CI/CD workflows

Frontend Architecture

Routing Structure

/                    → Public CV display
/admin               → Admin panel (requires auth)
/admin/login         → Login page
/admin/personal      → Personal info editor
/admin/experience    → Experience editor
/admin/skills        → Skills editor
/admin/education     → Education editor
/admin/projects      → Projects editor

Component Hierarchy

App
├── CVProvider (context)
│   └── AuthProvider (context)
│       ├── Routes
│       │   ├── "/" → CV Display Page
│       │   │   └── Hero, Experience, Skills, Education, Projects, Contact
│       │   └── "/admin/*" → AdminLayout
│       │       ├── LoginPage (unauthenticated)
│       │       └── Admin* Pages (authenticated)
│       │           └── *Form components

State Management

The application uses React Context for state management:

CVContext (src/admin/hooks/CVContext.jsx)

  • Manages CV data state
  • Provides useCVData() hook for components
  • Handles API communication for CRUD operations

AuthContext (src/admin/hooks/AuthContext.jsx)

  • Manages authentication state
  • Handles token storage and validation
  • Provides useAuth() hook for protected routes

Custom Hooks

Hook Purpose
useCVData() Access CV data and CRUD operations
useAuth() Access authentication state and methods
useFormValidation() Form validation with error handling

Styling

  • Tailwind CSS 4 with @tailwindcss/vite plugin
  • Utility-first approach throughout
  • Responsive design with mobile-first breakpoints
  • Animations via Framer Motion

Backend Architecture

API Endpoints

Endpoint Method Description Auth
/api/auth/config GET Get auth configuration No
/api/auth/login POST Authenticate with password No
/api/cv GET Get CV data No
/api/cv PUT Update CV data Yes
/api/cv/export GET Export CV as JSON No
/api/cv/import POST Import CV from JSON Yes
/api/docs GET Swagger UI documentation No
/health GET Health check endpoint No

Request/Response Examples

Get CV Data

GET /api/cv
Response: {
  "personal": { "name": "...", "title": "...", ... },
  "experience": [...],
  "skills": {...},
  "education": [...],
  "projects": [...]
}

Update CV Data

PUT /api/cv
Authorization: Bearer <token>
Body: { "personal": {...}, "experience": [...], ... }
Response: { "success": true }

Login

POST /api/auth/login
Body: { "password": "..." }
Response: { "token": "..." }

Database Schema

Single-table design for simplicity:

CREATE TABLE cv_data (
  id          INTEGER PRIMARY KEY CHECK (id = 1),
  data        TEXT NOT NULL,
  updated_at  DATETIME DEFAULT CURRENT_TIMESTAMP
);

The CV data is stored as a JSON document in the data column:

{
  "personal": {
    "name": "string",
    "title": "string",
    "intro": "string",
    "email": "string",
    "github": "string",
    "linkedin": "string",
    "location": "string"
  },
  "experience": [
    {
      "company": "string",
      "position": "string",
      "startDate": "YYYY-MM",
      "endDate": "YYYY-MM or null",
      "description": "string",
      "highlights": ["string", ...]
    }
  ],
  "skills": {
    "Category Name": ["skill1", "skill2", ...]
  },
  "education": [
    {
      "institution": "string",
      "degree": "string",
      "field": "string",
      "startDate": "YYYY",
      "endDate": "YYYY"
    }
  ],
  "projects": [
    {
      "name": "string",
      "description": "string",
      "technologies": ["tech1", ...],
      "url": "string"
    }
  ]
}

Authentication

Two authentication modes are supported:

Simple Mode (default)

  • Random password generated on server startup
  • Password logged to console
  • JWT token-based authentication
  • Suitable for personal/single-user deployments

Keycloak Mode (optional)

  • SSO integration via Keycloak
  • Configure via environment variables
  • Suitable for enterprise deployments

Environment variables for Keycloak:

AUTH_MODE=keycloak
KEYCLOAK_URL=https://keycloak.example.com
KEYCLOAK_REALM=your-realm
KEYCLOAK_CLIENT_ID=cv-app

Middleware

Auth Middleware (backend/middleware/auth.js)

  • Validates JWT token from Authorization header
  • Attaches user info to request
  • Returns 401 for invalid/missing tokens

Design Patterns

Frontend Patterns

  1. Context Provider Pattern

    • CVProvider and AuthProvider wrap the application
    • Provides global state without prop drilling
  2. Custom Hook Pattern

    • useCVData(), useAuth() expose context values
    • Encapsulates complex logic
  3. Container/Presentational Pattern

    • Admin pages fetch data from context (container)
    • Form components handle UI (presentational)
  4. Form Validation Pattern

    • useFormValidation hook provides reusable validation
    • Error state management standardized

Backend Patterns

  1. Route Handler Pattern

    • Modular Express routers in /routes
    • Clean separation of concerns
  2. Middleware Pattern

    • Auth middleware for protected routes
    • Composable request processing
  3. Repository Pattern

    • getDB() returns Knex instance
    • Database access abstracted from route handlers
  4. Migration-based Schema

    • Knex migrations for version control
    • Rollback capability

Testing Architecture

Layer Tool Location Purpose
Unit Vitest src/lib/__tests__/, src/admin/hooks/__tests__/ Test utilities and hooks
API Vitest + Supertest backend/__tests__/ Test API endpoints
Integration Vitest tests/integration/ Test full-stack interactions
E2E Playwright tests/e2e/ Test user flows
Regression Vitest tests/regression/ Snapshot tests
Performance k6, Lighthouse tests/performance/ Load and performance testing

Test Commands

npm run test:run          # Run unit tests
npm run test:coverage     # Run tests with coverage
npm run test:integration  # Run integration tests
npm run test:e2e          # Run E2E tests (requires running server)
npm run test:regression   # Run regression tests

Configuration

Frontend Configuration

Vite (vite.config.js)

  • React plugin with SWC
  • Tailwind CSS plugin
  • Proxy configuration for API

Tailwind (src/index.css)

  • Tailwind imports
  • Custom CSS variables

Backend Configuration

Environment Variables

Variable Default Description
PORT 3001 Server port
AUTH_MODE simple Authentication mode (simple/keycloak)
KEYCLOAK_URL - Keycloak server URL
KEYCLOAK_REALM - Keycloak realm
KEYCLOAK_CLIENT_ID - Keycloak client ID

Knex (backend/knexfile.js)

  • SQLite database configuration
  • Migration and seed directories

Development

Prerequisites

  • Node.js 20+
  • npm 10+

Getting Started

# Install frontend dependencies
npm install

# Install backend dependencies
cd backend && npm install

# Start backend server
npm run dev:backend

# In another terminal, start frontend
npm run dev

Build

# Build frontend
npm run build

# Build outputs to dist/

Docker

# Build and run with Docker Compose
docker-compose up --build

The Docker setup includes:

  • Frontend container with nginx
  • Backend container with Node.js
  • SQLite volume for persistence

Security Considerations

  1. Authentication: JWT tokens with configurable expiration
  2. Secret Scanning: Gitleaks pre-commit hook
  3. Input Validation: Form validation on frontend, schema validation on backend
  4. CORS: Configured for frontend origin
  5. SQL Injection: Knex query builder prevents injection

Future Considerations

  • Image Upload: Profile picture support
  • PDF Export: Generate PDF from CV data
  • Themes: Customizable color schemes
  • Multi-language: Internationalization support
  • Analytics: View tracking for CV