# Spécification de Design: Portfolio Geekbrain.io **Date:** 2025-03-21 **Statut:** Brouillon **Auteur:** Claude (avec Eric Chicoine) --- ## 1. Vision et Objectifs ### 1.1 But du projet Créer un site portfolio professionnel pour présenter les activités de développeur Python/Agentique freelance sous la marque Geekbrain.io. ### 1.2 Objectifs spécifiques - Présenter les compétences et expériences - Afficher les projets via une liste dynamique tirée du GitBucket local - Permettre aux clients potentiels de contacter via un formulaire - Design steampunk professionnel moderne - Hébergement sur NAS Docker avec Nginx Proxy Manager - Maintenance simple et contrôle total du code --- ## 2. Exigences ### 2.1 Exigences fonctionnelles #### Pages - **Accueil**: Hero section, résumé, services, compétences principales, CTA - **À propos**: Parcours, photo, compétences détaillées - **Projets**: Liste automatique des repos GitBucket (nom + description README) - **Contact**: Formulaire avec validation, reCAPTCHA, envoi email + stockage BD #### Formulaire de contact Champs: - Nom (obligatoire) - Email (obligatoire, validation email) - Sujet (obligatoire) - Message (obligatoire) - Soumis avec reCAPTCHA v2 Traitement: - Validation frontend + backend - Stockage en base de données (table `contacts`) - Envoi email via SMTP Gmail ([email protected]) - Réponse HTTP appropriée (succès/erreur) #### Affichage des projets - Appel API GitBucket: `http://10.0.0.16:8080/api/v3/users/rcairbum/repos` - Extraction: `name` + `description` - Affichage en cartes **sans lien** vers le repo GitBucket (projets affichés en lecture seule) - Si API down ou erreur: afficher "Projets temporairement indisponibles" - Cache: 5 minutes - Note: Les repos seront configurés en **public** sur GitBucket, donc pas besoin d'authentification ### 2.2 Exigences non-fonctionnelles #### Performance - Site rapide (FastAPI asynchrone) - Cache des appels GitBucket (éviter requêtes fréquentes) #### Sécurité - reCAPTCHA pour anti-spam - Validation backend complète - Pas d'injection SQL (SQLAlchemy ORM) - Variables d'environnement pour secrets (SMTP, DB) - Headers de sécurité (CORS, etc.) #### Hébergement - Docker container isolé - Utilisation MariaDB existante - Proxy via Nginx Proxy Manager - HTTPS automatique via Let's Encrypt #### Maintenance - Configuration via variables d'environnement - Logs structurés - Code modulaire et documenté --- ## 3. Architecture Technique ### 3.1 Stack - **Backend:** FastAPI 0.104+ (Python 3.11+) - **Frontend:** Jinja2 templates + CSS personnalisé - **Base de données:** MariaDB (10.0.0.16:3306) - **ORM:** SQLAlchemy 2.0+ avec asyncpg (async) - **Validation:** Pydantic v2 - **Email:** aiosmtplib (async SMTP) - **Container:** Docker + docker-compose - **Proxy:** Nginx Proxy Manager - **API externe:** GitBucket REST API (compatible GitHub v3) ### 3.2 Structure du projet ``` geekbrain-portfolio/ ├── app/ │ ├── __init__.py │ ├── main.py # FastAPI app, routes │ ├── config.py # Configuration (env vars) │ ├── database.py # DB connection, session │ ├── models.py # SQLAlchemy models │ ├── schemas.py # Pydantic schemas │ ├── crud.py # Database operations │ ├── routes/ │ │ ├── home.py │ │ ├── about.py │ │ ├── projects.py │ │ └── contact.py │ ├── services/ │ │ ├── gitbucket.py # Fetch repos from GitBucket │ │ └── email.py # Send contact email │ ├── templates/ │ │ ├── base.html # Steampunk theme │ │ ├── index.html │ │ ├── about.html │ │ ├── projects.html │ │ └── contact.html │ ├── static/ │ │ ├── css/ │ │ │ └── style.css # Steampunk styling │ │ ├── js/ │ │ │ └── main.js # Frontend validation, reCAPTCHA │ │ └── assets/ # Logo et images (copié depuis public/assets/) │ │ └── images/ # Contient Geekbrain-io.png └── docker/ ├── Dockerfile ├── docker-compose.yml └── .env.example ``` ### 3.3 Docker **Dockerfile:** ```dockerfile FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] ``` **docker-compose.yml:** ```yaml version: '3.8' services: web: build: . ports: - "8000:8000" environment: - DATABASE_URL=mysql+aiomysql://geekbrain_app:${DB_PASSWORD}@10.0.0.16:3306/geekbrain_portfolio - SMTP_HOST=${SMTP_HOST} - SMTP_PORT=${SMTP_PORT} - SMTP_USER=${SMTP_USER} - SMTP_PASSWORD=${SMTP_PASSWORD} - RECAPTCHA_SECRET=${RECAPTCHA_SECRET} - GITBUCKET_URL=http://10.0.0.16:8080/api/v3/users/rcairbum/repos volumes: - ./app/static:/app/static restart: unless-stopped ``` ### 3.4 Base de données #### Création MariaDB (à exécuter sur le serveur DB) ```sql CREATE DATABASE geekbrain_portfolio CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'geekbrain_app'@'%' IDENTIFIED BY '${APP_DB_PASSWORD}'; GRANT SELECT, INSERT, UPDATE, DELETE ON geekbrain_portfolio.* TO 'geekbrain_app'@'%'; FLUSH PRIVILEGES; ``` *(Privilèges restreints aux opérations nécessaires, pas ALL PRIVILEGES pour plus de sécurité)* #### Schéma **Table `contacts`:** ```sql CREATE TABLE contacts ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL, subject VARCHAR(255) NOT NULL, message TEXT NOT NULL, submitted_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, ip_address VARCHAR(45), recaptcha_score FLOAT ); ``` (Optionnel) Table `site_settings` pour config future? --- ## 4. Modèles de données (SQLAlchemy) ### Contact ```python class Contact(Base): __tablename__ = "contacts" id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] = mapped_column(String(255)) email: Mapped[str] = mapped_column(String(255)) subject: Mapped[str] = mapped_column(String(255)) message: Mapped[str] = mapped_column(Text) submitted_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow) ip_address: Mapped[Optional[str]] = mapped_column(String(45)) ``` --- ## 5. API Endpoints (FastAPI) | Méthode | Path | Description | |---------|------|-------------| | GET | `/` | Page d'accueil | | GET | `/about` | Page à propos | | GET | `/projects` | Page projets (appelle GitBucket API) | | GET | `/contact` | Page contact (formulaire) | | POST | `/contact` | Soumission formulaire (validate + save + email) | | GET | `/health` | Health check (pour monitoring) | ### POST `/contact` body ```json { "name": "Jean Dupont", "email": "[email protected]", "subject": "Demande de devis", "message": "Bonjour, je souhaite...", "recaptcha_token": "token_from_frontend" } ``` ### Response ```json { "success": true, "message": "Message envoyé avec succès" } ``` --- ## 6. Design UI/UX ### 6.1 Palette Steampunk Pro Moderne - **Primaire:** Laiton doré `#D4AF37` (boutons, accents) - **Secondaire:** Gris acier `#4a4a4a` (textes secondaires, fonds sombres) - **Fond clair:** Blanc cassé `#F5F5DC` (cartes, contenu) - **Fond sombre:** Noir charbon `#1a1a1a` (header, footer, hero) - **Accent:** Cuivre `#B87333` (gradients, hover) ### 6.2 Typographie - Headers: Times New Roman, Georgia (serif) - Body: System fonts (sans-serif pour lisibilité) - Tailles généreuses, espacement aéré ### 6.3 Layout - Header sombre avec logo (`public/assets/images/Geekbrain-io.png`) à gauche, nav alignée droite - Navigation horizontale desktop, hamburger menu mobile - Hero section avec gradient doré et call-to-action - Grille responsive pour projets et cartes - Footer sombre avec copyright + LinkedIn - Bordure `2px solid #D4AF37` sur cartes/hero ### 6.4 Responsive - Mobile-first CSS - Breakpoints: 768px, 1024px - Navigation adaptative --- ## 7. Configuration Variables d'environnement requises: | Variable | Description | obligatoire | |----------|-------------|-------------| | `DATABASE_URL` | Connection MariaDB (SQLAlchemy format) | Oui | | `SMTP_HOST` | Serveur SMTP (smtp.gmail.com) | Oui | | `SMTP_PORT` | Port SMTP (587) | Oui | | `SMTP_USER` | Email expéditeur ([email protected]) | Oui | | `SMTP_PASSWORD` | Mot de passe/mot de passe d'appli Gmail | Oui | | `RECAPTCHA_SECRET` | Clé secrète reCAPTCHA v2 | Oui | | `GITBUCKET_URL` | URL API GitBucket | Oui | | `CACHE_TTL` | Cache API GitBucket en secondes (défaut: 300) | Non | --- ## 8. Sécurité ### 8.1 reCAPTCHA - reCAPTCHA v2 ("I'm not a robot") sur formulaire - Vérification backend via secret key - Score/threshold pour détecter bots ### 8.2 Validation - Pydantic pour schémas de données - Validation email, longueur, caractères - Protection CSRF? (pas nécessaire pour API simple) ### 8.3 Headers - CORS configuré (allow origins si besoin) - X-Content-Type-Options: nosniff - X-Frame-Options: DENY ### 8.4 Secrets - Variables d'environnement uniquement - Jamais commit de .env - Supporter configurer via Docker secrets/swarm si nécessaire --- ## 9. Intégrations externes ### 9.1 GitBucket API - Endpoint: `http://10.0.0.16:8080/api/v3/users/rcairbum/repos` - Méthode: GET - Format: JSON (compatible GitHub API v3) - Authentication: **Non requis** (les repos seront configurés en public) - Cache: 5 minutes par défaut (pour éviter surcharge) - Fallback: Si erreur/timeout, afficher message "Projets temporairement indisponibles" ### 9.2 Email (SMTP) - SMTP Gmail (TLS) - Destinataire: [email protected] (ou configurable) - Expéditeur: même que SMTP_USER - Template d'email simple avec infos du contact ### 9.3 reCAPTCHA - Version v2 (checkbox) - Site key en frontend (dans template) - Secret key en backend (variable env) - Vérification via API Google --- ## 10. Hébergement et Déploiement ### 10.1 Prérequis sur NAS - Docker installé - Docker Compose - MariaDB accessible (10.0.0.16:3306) - Nginx Proxy Manager (NPM) installé ### 10.2 Étapes de déploiement 1. **Configurer la base de données MariaDB** (sur le serveur DB): ```sql CREATE DATABASE geekbrain_portfolio CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'geekbrain_app'@'%' IDENTIFIED BY 'UN_MOT_DE_PASSE_SECURISE'; GRANT ALL PRIVILEGES ON geekbrain_portfolio.* TO 'geekbrain_app'@'%'; FLUSH PRIVILEGES; ``` 2. **Préparer le container Docker:** - Cloner/construire l'application - Créer `.env` à partir de `.env.example` - Renseigner variables (DB password, SMTP, reCAPTCHA, etc.) 3. **Démarrer le service:** ```bash docker-compose up -d ``` 4. **Configurer Nginx Proxy Manager:** - Ajouter un "Proxy Host" - Domain names: `portfolio.geekbrain.io` - Scheme: http, Host: IP_DU_NAS, Port: 8000 - Activer SSL (Let's Encrypt) - Activer WebSockets si besoin (pas nécessaire ici) 5. **Vérifier:** - Site accessible via https://portfolio.geekbrain.io - Formulaire fonctionne, emails reçus - Projets s'affichent depuis GitBucket ### 10.3 Mise à jour ```bash git pull <repo> docker-compose down docker-compose up -d --build ``` --- ## 11. Maintenance et Monitoring ### 11.1 Logs - FastAPI logs structurés (JSON si possible) - Docker logs (`docker-compose logs -f web`) - Configuration niveau log via variable env (`LOG_LEVEL`) ### 11.2 Health check Endpoint `/health` retourne 200 si DB connectée. ### 11.3 Sauvegardes - Backup MariaDB automatique (géré au niveau NAS) - Backup code Git (hors périmètre) ### 11.4 Monitoring - Métriques FastAPI (optionnel) - Monitoring Docker via Portainer ou Watchtower --- ## 12. Évolution future (backlog) - Interface admin pour gérer projets (au lieu de GitBucket API) - Blog technique avec articles markdown - Multilanguage (i18n) - Stats de visites (Plausible/Umami) - Notification Slack/Discord pour nouveaux contacts - Export contacts CSV - Thème sombre/clair --- ## 13. Risques et Contraintes ### 13.1 Risques - GitBucket API non accessible depuis container (réseau) → utiliser SSHFS ou API publique? - Spam malgré reCAPTCHA → prévoir rate limiting - SMTP Gmail limitations (quotas) → prévoir alternative - dépendandance à GitBucket privé → considérer copie locale ### 13.2 Contraintes - Doit fonctionner sur NAS avec ressources limitées (RAM/CPU) - Version MariaDB existante (compatibilité SQLAlchemy) - Accès réseau local à GitBucket (10.0.0.16) --- ## 14. Tests ### 14.1 Tests unitaires - Modèles Pydantic - Fonctions de validation - Crud opérations ### 14.2 Tests d'intégration - Endpoints API (TestClient) - Connexion DB - Envoi email (mock SMTP) ### 14.3 Tests manuels - Formulaire soumission avec/erreurs - Affichage projets (mocked API) - Responsive design --- ## 15. Suivi et Acceptation ### Critères d'acceptation - [ ] Site visible sur portfolio.geekbrain.io avec HTTPS - [ ] Pages Accueil, À propos, Projets, Contact fonctionnelles - [ ] Formulaire envoie email + stocke en BD - [ ] reCAPTCHA fonctionnel (pas de spam) - [ ] Liste projets dynamique depuis GitBucket - [ ] Design steampunk pro (validé) - [ ] Responsive mobile/desktop - [ ] Dockerisé, logs, health check - [ ] Variables d'env configurées - [ ] Code documenté, structure claire --- **Prochaines étapes:** 1. Valider cette spécification 2. Créer le plan d'implémentation détaillé (writing-plans) 3. Implémenter par phases (setup, DB, routes, templates, intégrations, Docker) 4. Tester et déployer --- *Document generated by Claude Code - superpowers:brainstorming*