No description
  • TypeScript 68%
  • CSS 21.6%
  • Nunjucks 9.1%
  • Dockerfile 0.9%
  • JavaScript 0.3%
  • Other 0.1%
Find a file
Julien LEQUEN da3e6d9da1 docs: URL de clone du dépôt dans le README
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 18:35:55 +02:00
prisma Cursus — éditeur de CV auto-hébergé 2026-06-16 15:30:51 +02:00
public Cursus — éditeur de CV auto-hébergé 2026-06-16 15:30:51 +02:00
src Cursus — éditeur de CV auto-hébergé 2026-06-16 15:30:51 +02:00
themes Cursus — éditeur de CV auto-hébergé 2026-06-16 15:30:51 +02:00
.dockerignore Cursus — éditeur de CV auto-hébergé 2026-06-16 15:30:51 +02:00
.env.example Cursus — éditeur de CV auto-hébergé 2026-06-16 15:30:51 +02:00
.gitignore Cursus — éditeur de CV auto-hébergé 2026-06-16 15:30:51 +02:00
docker-compose.yml Cursus — éditeur de CV auto-hébergé 2026-06-16 15:30:51 +02:00
docker-entrypoint.sh Cursus — éditeur de CV auto-hébergé 2026-06-16 15:30:51 +02:00
Dockerfile Cursus — éditeur de CV auto-hébergé 2026-06-16 15:30:51 +02:00
next.config.mjs Cursus — éditeur de CV auto-hébergé 2026-06-16 15:30:51 +02:00
package-lock.json Cursus — éditeur de CV auto-hébergé 2026-06-16 15:30:51 +02:00
package.json Cursus — éditeur de CV auto-hébergé 2026-06-16 15:30:51 +02:00
postcss.config.mjs Cursus — éditeur de CV auto-hébergé 2026-06-16 15:30:51 +02:00
README.md docs: URL de clone du dépôt dans le README 2026-06-16 18:35:55 +02:00
tsconfig.json Cursus — éditeur de CV auto-hébergé 2026-06-16 15:30:51 +02:00

Cursus

Cursus est une application web auto-hébergée pour créer, héberger et exporter un CV. On édite son CV en ligne (enregistrement automatique), on le publie à une URL publique, et on l'exporte en PDF A4 au rendu identique quel que soit le navigateur — la génération est faite côté serveur par un Chromium headless.

Le logo reprend la case de l'élément Cu (n°29) du tableau périodique — clin d'œil à Cursus.


Fonctionnalités

  • ✍️ Éditeur en ligne avec enregistrement automatique (aucun bouton « Enregistrer ») et interface en barre latérale.
  • 🌐🔒 CV public et CV privé : chaque section / contact / élément a une visibilité Public, Privé ou Public et privé.
  • 🎨 7 thèmes intégrés + thèmes « fichiers » : déposez un dossier (theme.json + template.njk + styles.css) dans themes/ et il apparaît au runtime, sans recompiler (voir themes/README.md).
  • 🖨️ Export PDF déterministe (A4, marges par thème) identique à l'écran, généré par Playwright/Chromium.
  • 📄 Aperçu paginé sur le web : la page s'affiche comme le PDF (feuilles A4 empilées), avec respect de l'option « ne pas couper un bloc ».
  • 🖼️ Photo avec recadrage / zoom / rotation avant upload.
  • 🔁 Export / Import JSON du CV complet.
  • 🧩 Sections repliables, champs contextuels selon le type de section, couleur d'accent et taille de texte réglables.

Prérequis

  • Docker et Docker Compose v2 (docker compose …).
  • Rien d'autre : Node, la base SQLite et le Chromium d'export PDF sont embarqués dans l'image.

Déploiement avec Docker Compose (pas à pas)

1. Récupérer le projet

git clone https://forge.lequen.fr/jlequen/Cursus.git cursus
cd cursus

2. Créer le fichier de configuration .env

cp .env.example .env

Puis éditez .env et renseignez au minimum :

Variable À mettre
AUTH_SECRET Un secret long et aléatoire — générez-le avec la commande ci-dessous
ADMIN_EMAIL L'email de connexion à l'éditeur
ADMIN_PASSWORD Le mot de passe initial de ce compte
PUBLIC_BASE_URL L'URL publique finale (ex. https://cv.mon-domaine.fr)
APP_PORT Le port exposé sur l'hôte (par défaut 63546)

Générer un AUTH_SECRET solide :

openssl rand -base64 32

⚠️ .env contient vos secrets et n'est pas versionné (il est dans .gitignore). Ne le committez jamais.

3. Construire et lancer

docker compose up -d --build

Au premier démarrage, le conteneur applique les migrations, crée le compte admin (à partir de ADMIN_EMAIL / ADMIN_PASSWORD) puis démarre l'app. Suivez les logs :

docker compose logs -f

4. Accéder à l'application

(Remplacez le port si vous avez changé APP_PORT.)

Le CV est vide au départ : tout se remplit dans l'éditeur, ou via Import JSON.

5. Mettre à jour, arrêter, redémarrer

# Récupérer une nouvelle version puis reconstruire
git pull
docker compose up -d --build

# Arrêter (les données sont conservées dans le volume)
docker compose down

# Voir les logs
docker compose logs -f

Mise en production derrière un reverse proxy

Le conteneur écoute en interne sur le port 3000 et est exposé sur l'hôte via APP_PORT (63546 par défaut). Placez un reverse proxy (Nginx, Caddy, Traefik…) devant, en TLS, qui transmet vers http://127.0.0.1:63546, et réglez PUBLIC_BASE_URL sur l'URL HTTPS publique.


Configuration (variables d'environnement)

Variable Défaut Rôle
APP_PORT 63546 Port exposé sur l'hôte
ADMIN_EMAIL admin@example.com Login de l'éditeur (créé au 1er démarrage)
ADMIN_PASSWORD changeme-please Mot de passe initial (à changer !)
AUTH_SECRET Secret de signature des sessions JWT (obligatoire)
PUBLIC_BASE_URL http://localhost:3000 URL publique (liens canoniques / rendu PDF)
DATABASE_URL file:/app/data/cv.db Base SQLite (sur le volume persistant)
THEMES_DIR /app/themes Dossier des thèmes fichiers (monté en volume)
CHROMIUM_PATH /usr/bin/chromium Chromium headless pour l'export PDF (fourni par l'image)

Le mot de passe n'est créé qu'au premier démarrage. Pour le changer ensuite, utilisez Compte → Changer le mot de passe dans l'éditeur (modifier ADMIN_PASSWORD après coup n'a pas d'effet).


Données & sauvegarde

  • Toutes les données (base SQLite + photos uploadées) vivent dans le volume Docker cv-data — elles survivent à down / up / --build.
  • Sauvegarde rapide du contenu : éditeur → Compte → Exporter en JSON. Restauration via Importer.
  • Sauvegarde du volume complet :
docker run --rm -v cv-data:/data -v "$PWD":/backup alpine \
  tar czf /backup/cv-data-backup.tar.gz -C /data .

Thèmes

Deux possibilités :

  1. Thèmes intégrés (déjà livrés) : sélectionnables dans Apparence → Thème.
  2. Thèmes fichiers : déposez un dossier dans themes/ (monté en volume), rechargez la page — aucun rebuild. Format et variables documentés dans themes/README.md.

Sécurité

  • Changez AUTH_SECRET et ADMIN_PASSWORD avant toute mise en ligne.
  • .env, la base de données (*.db, /data) et les sauvegardes (/backups) sont exclus du dépôt (.gitignore) : aucun secret ni donnée personnelle n'est versionné.
  • Servez l'application en HTTPS derrière un reverse proxy.

Développement local (sans Docker)

npm install
cp .env.example .env          # adaptez DATABASE_URL en local si besoin
npx prisma migrate deploy
npm run seed
npm run dev                   # http://localhost:3000

L'export PDF en local nécessite un Chromium/Chrome installé ; pointez CHROMIUM_PATH dessus.


Stack technique

  • Next.js 15 (App Router) · React 19 · TypeScript · Tailwind CSS v4
  • Prisma + SQLite
  • Playwright (Chromium headless) pour l'export PDF A4 déterministe
  • Nunjucks (+ marked / sanitize-html) pour les thèmes fichiers
  • Authentification par session JWT (jose) + bcrypt