Construire un portfolio open-source moderne avec Nuxt 3 — thèmes CSS, données JSON, SEO automatique, et déploiement Docker.
OpenFolio supporte deux modes de déploiement : Docker sur un VPS, ou Vercel/Netlify pour du serverless. Les deux partent du même code.
Le Dockerfile inclus dans le repo utilise une build multi-étapes pour minimiser la taille de l'image finale.
# Étape 1 — build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Étape 2 — image finale
FROM node:20-alpine AS runner
WORKDIR /app
COPY --from=builder /app/.output ./output
ENV HOST=0.0.0.0
ENV PORT=3000
EXPOSE 3000
CMD ["node", "output/server/index.mjs"]npm run build avec Nuxt génère .output/ — un dossier autonome qui contient tout : le serveur Node, les assets statiques, et les chunks JavaScript. Aucune dépendance node_modules à copier dans l'image finale.
# Build l'image
docker build -t openfolio .
# Run en local
docker run -p 3000:3000 openfolio
# Run en production (restart automatique)
docker run -d --restart unless-stopped -p 3000:3000 --name openfolio openfolio-d detache le conteneur. --restart unless-stopped le relance automatiquement si le serveur redémarre.
Si le VPS héberge plusieurs services (Nginx, base de données...) :
services:
openfolio:
build: .
restart: unless-stopped
ports:
- "3000:3000"
environment:
- NODE_ENV=productiondocker compose up -dEn production, Nginx fait le SSL et redirige vers le conteneur :
server {
listen 80;
server_name votre-domaine.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name votre-domaine.com;
ssl_certificate /etc/letsencrypt/live/votre-domaine.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/votre-domaine.com/privkey.pem;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}Certbot génère le certificat SSL Let's Encrypt gratuitement :
certbot --nginx -d votre-domaine.comPour Vercel, changer le preset dans nuxt.config.ts :
nitro: {
preset: 'vercel',
},Puis pusher sur GitHub et connecter le repo dans le dashboard Vercel. Le build se lance automatiquement à chaque push sur main.
Vercel détecte Nuxt automatiquement — aucune configuration supplémentaire.
nitro: {
preset: 'netlify',
},Créer un fichier netlify.toml à la racine :
[build]
command = "npm run build"
publish = ".output/public"
[build.environment]
NODE_VERSION = "20"Avec Docker sur VPS, le workflow de mise à jour est :
git pull
docker build -t openfolio .
docker stop openfolio
docker rm openfolio
docker run -d --restart unless-stopped -p 3000:3000 --name openfolio openfolioOu avec Docker Compose :
git pull
docker compose up -d --build--build force la reconstruction de l'image même si le Dockerfile n'a pas changé.
Puisque les JSON sont dans /public/data/, ils sont servis comme fichiers statiques. Sur un VPS, on peut modifier un JSON directement sur le serveur et les visiteurs voient la mise à jour au prochain rafraîchissement — sans rebuild Docker.
# Éditer un projet directement sur le serveur
ssh user@votre-serveur
vim /chemin/vers/OpenFolio/public/data/projects.jsonC'est l'un des avantages du modèle "pas de base de données" : le contenu est juste des fichiers.