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

449 lines
13 KiB
Markdown

<!-- markdownlint-disable MD013 -->
# 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**
```http
GET /api/cv
Response: {
"personal": { "name": "...", "title": "...", ... },
"experience": [...],
"skills": {...},
"education": [...],
"projects": [...]
}
```
**Update CV Data**
```http
PUT /api/cv
Authorization: Bearer <token>
Body: { "personal": {...}, "experience": [...], ... }
Response: { "success": true }
```
**Login**
```http
POST /api/auth/login
Body: { "password": "..." }
Response: { "token": "..." }
```
### Database Schema
Single-table design for simplicity:
```sql
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:
```json
{
"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:
```bash
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
```bash
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
```bash
# 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
```bash
# Build frontend
npm run build
# Build outputs to dist/
```
### Docker
```bash
# 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