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
This commit is contained in:
448
docs/architecture.md
Normal file
448
docs/architecture.md
Normal file
@@ -0,0 +1,448 @@
|
|||||||
|
<!-- 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
|
||||||
Reference in New Issue
Block a user