# CV - Tuan-Dat Tran ![License](https://img.shields.io/badge/license-MIT-blue.svg) ![React](https://img.shields.io/badge/React-18-61DAFB?logo=react) ![Tailwind CSS](https://img.shields.io/badge/Tailwind-4.1-38B2AC?logo=tailwindcss) ![Vite](https://img.shields.io/badge/Vite-7-646CFF?logo=vite) A modern, minimalist CV/Resume single-page application with admin panel and persistent storage. ## Architecture ``` ┌─────────────────────────────────────────────────────┐ │ Docker Compose │ │ ┌──────────────┐ ┌──────────────────────────┐ │ │ │ Frontend │ │ Backend API │ │ │ │ (React) │───▶│ (Express.js) │ │ │ │ Port 5173 │ │ Port 3001 │ │ │ └──────────────┘ └───────────┬──────────────┘ │ │ │ │ │ ┌───────────▼──────────────┐ │ │ │ SQLite DB │ │ │ │ (Volume: ./data) │ │ │ └──────────────────────────┘ │ └─────────────────────────────────────────────────────┘ ``` ## Features - Modern, responsive design - Smooth scroll animations with Framer Motion - Admin panel for easy CV editing (password protected) - Persistent storage with SQLite - Docker Compose deployment - API-based architecture - Optional Keycloak integration for SSO ## Tech Stack ### Frontend - **React 18** - UI Library - **Vite** - Build Tool - **Tailwind CSS 4** - Styling - **Framer Motion** - Animations - **Lucide React** - Icons ### Backend - **Express.js** - API Server - **SQLite** - Database - **better-sqlite3** - SQLite driver ## Getting Started ### Prerequisites - Node.js 18+ - npm 9+ - Docker & Docker Compose (optional) ### Option 1: Docker Compose (Recommended) ```bash # Start all services docker-compose up -d # Frontend: http://localhost:5173 # Backend API: http://localhost:3001 # Admin Panel: http://localhost:5173/admin ``` ### Option 2: Local Development ```bash # Install frontend dependencies npm install # Install backend dependencies cd backend && npm install && cd .. # Start backend (terminal 1) cd backend && npm run dev # Start frontend (terminal 2) npm run dev ``` ### Environment Variables Frontend (`.env`): ``` VITE_API_URL=http://localhost:3001 ``` Backend (`backend/.env`): ``` PORT=3001 DB_PATH=./data/cv.db USE_KEYCLOAK=false # Keycloak settings (required if USE_KEYCLOAK=true) KEYCLOAK_URL=https://keycloak.example.com KEYCLOAK_REALM=your-realm KEYCLOAK_CLIENT_ID=cv-admin ``` ## Development Setup ### Pre-commit Setup This project uses Gitleaks for secret scanning. Install it before committing: ```bash # macOS brew install gitleaks # Linux curl -sSfL https://github.com/gitleaks/gitleaks/releases/latest/download/gitleaks_linux_x64.tar.gz | tar -xz sudo mv gitleaks /usr/local/bin/ # Windows scoop install gitleaks ``` ### API Documentation API documentation is available at `/api/docs` when running the server. Access the interactive Swagger UI at: `http://localhost:3001/api/docs` ## Admin Authentication ### Simple Mode (Default) - A random password is generated and printed to the console on server startup - Look for the "ADMIN PASSWORD" banner in the logs - Enter this password to access the admin panel ### Keycloak Mode Set `USE_KEYCLOAK=true` and configure Keycloak environment variables: ```bash USE_KEYCLOAK=true KEYCLOAK_URL=https://keycloak.example.com KEYCLOAK_REALM=your-realm KEYCLOAK_CLIENT_ID=cv-admin ``` ## API Endpoints | Method | Endpoint | Auth | Description | |--------|----------|------|-------------| | GET | `/api/cv` | No | Get CV data | | PUT | `/api/cv` | Yes | Update CV data | | GET | `/api/cv/export` | No | Export as JSON | | POST | `/api/cv/import` | Yes | Import JSON data | | GET | `/api/auth/config` | No | Get auth configuration | | POST | `/api/auth/login` | No | Login with password | | GET | `/api/docs` | No | Swagger API documentation | | GET | `/health` | No | Health check | ## Project Structure ``` . ├── src/ # Frontend source │ ├── components/ # CV components │ ├── admin/ # Admin panel │ ├── lib/ # Utilities │ └── App.jsx ├── backend/ # Backend source │ ├── routes/ # API routes │ ├── db/ # Database │ └── server.js ├── docker-compose.yml ├── Dockerfile └── nginx.conf ``` ## Testing ```bash # Frontend tests npm run test:run # Backend tests cd backend && npm test ``` ## Release Process This project uses [semantic-release](https://semantic-release.gitbook.io/) for automated versioning and releases. ### Conventional Commits All commit messages must follow the [Conventional Commits](https://www.conventionalcommits.org/) specification: ``` (): [optional body] [optional footer] ``` #### Commit Types | Type | Description | Version Bump | |------|-------------|--------------| | `feat` | New feature | Minor | | `fix` | Bug fix | Patch | | `feat!` or `BREAKING CHANGE` | Breaking change | Major | | `docs`, `style`, `refactor`, `test`, `build`, `ci`, `chore` | Non-release changes | None | #### Scopes Available scopes: `admin`, `api`, `ui`, `docker`, `ci`, `deps`, `release`, `auth`, `skills`, `experience`, `education`, `projects`, `personal` ### Release Workflow 1. Push to `master` branch 2. CI runs tests and linting 3. semantic-release analyzes commits 4. If release needed: - Version is bumped in package.json - CHANGELOG.md is updated - Git tag is created - GitHub release is published - Docker images are built and pushed ### Docker Images Images are published to both Docker Hub and GitHub Container Registry: | Tag | Description | |-----|-------------| | `latest` | Latest stable release | | `v1.2.3` | Specific version | | `staging` | Staging environment | | `nightly`, `edge` | Daily builds from master | | `YYYY-MM-DD` | Dated nightly build | ```bash # Pull from Docker Hub docker pull username/cv-app:latest # Pull from GHCR docker pull ghcr.io/owner/cv-app:latest ``` ### Environments | Environment | Branch | Trigger | |-------------|--------|---------| | Production | `master` | semantic-release | | Staging | `staging` | Push to staging | | Nightly | `master` | Daily at 02:00 UTC | For detailed documentation, see [Release Engineering Documentation](docs/release-engineering.md). ## Documentation | Document | Description | |----------|-------------| | [Release Engineering](docs/release-engineering.md) | Comprehensive release pipeline documentation | | [Contributing](CONTRIBUTING.md) | Contribution guidelines | | [Security](SECURITY.md) | Security policy | ## Contributing Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details. ## License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.