docs(03): create phase 3 plans — pages, components, Docker SSR
4 plans across 3 waves: shared components + deps (wave 1), pages landing/projects/detail + about/contact/fiverr/404 (wave 2), Dockerfile SSR + GA4 + docker-compose (wave 3).
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
---
|
||||
phase: 03-pages-ship
|
||||
plan: 04
|
||||
type: execute
|
||||
wave: 3
|
||||
depends_on: ["03-02", "03-03"]
|
||||
files_modified:
|
||||
- Dockerfile
|
||||
- docker-compose.yml
|
||||
- nuxt.config.ts
|
||||
- app/pages/formation.vue
|
||||
autonomous: true
|
||||
requirements:
|
||||
- INFRA-01
|
||||
- INFRA-04
|
||||
- PAGE-07
|
||||
must_haves:
|
||||
truths:
|
||||
- "docker build -t portfolio . reussit sans erreur"
|
||||
- "docker run -p 3000:3000 portfolio sert l'app SSR sur port 3000"
|
||||
- "GA4 est actif uniquement en production"
|
||||
- "Route /formation redirige vers / ou retourne 404"
|
||||
artifacts:
|
||||
- path: "Dockerfile"
|
||||
provides: "Multi-stage SSR build node:22-alpine"
|
||||
- path: "docker-compose.yml"
|
||||
provides: "Config Traefik avec port 3000"
|
||||
key_links:
|
||||
- from: "Dockerfile"
|
||||
to: ".output/server/index.mjs"
|
||||
via: "node .output/server/index.mjs"
|
||||
pattern: "node.*\\.output/server/index\\.mjs"
|
||||
- from: "docker-compose.yml"
|
||||
to: "Traefik"
|
||||
via: "loadbalancer.server.port=3000"
|
||||
pattern: "port=3000"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Finaliser l'infrastructure de deploiement : Dockerfile SSR multi-stage, config GA4 production-only, mise a jour docker-compose Traefik, gestion de la page formation supprimee, et nettoyage legacy.
|
||||
|
||||
Purpose: Rend le portfolio deployable en production via Docker + Traefik avec analytics.
|
||||
Output: Dockerfile SSR fonctionnel, GA4 configure, docker-compose mis a jour.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@C:\Users\minit\.claude\get-shit-done\workflows\execute-plan.md
|
||||
@C:\Users\minit\.claude\get-shit-done\templates\summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/phases/03-pages-ship/03-CONTEXT.md
|
||||
@.planning/phases/03-pages-ship/03-RESEARCH.md
|
||||
@.planning/phases/03-pages-ship/03-02-SUMMARY.md
|
||||
@.planning/phases/03-pages-ship/03-03-SUMMARY.md
|
||||
|
||||
@Dockerfile
|
||||
@docker-compose.yml
|
||||
@nuxt.config.ts
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Dockerfile SSR multi-stage + docker-compose Traefik port 3000</name>
|
||||
<files>Dockerfile, docker-compose.yml</files>
|
||||
<action>
|
||||
**Dockerfile** (per D-12, D-13, INFRA-01) : Reecrire completement le Dockerfile existant (qui copie dist/ vers nginx). Implementation exacte du RESEARCH.md Pattern 6 :
|
||||
|
||||
```dockerfile
|
||||
# Stage 1: Build
|
||||
FROM node:22-alpine AS builder
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm ci
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
# Stage 2: Runtime
|
||||
FROM node:22-alpine AS runner
|
||||
ENV NODE_ENV=production
|
||||
ENV HOST=0.0.0.0
|
||||
ENV PORT=3000
|
||||
WORKDIR /app
|
||||
COPY --from=builder /app/.output /app/.output
|
||||
EXPOSE 3000
|
||||
CMD ["node", "/app/.output/server/index.mjs"]
|
||||
```
|
||||
|
||||
IMPORTANT : Copie `.output/` PAS `dist/` (per RESEARCH.md Pitfall 3). Pas de nginx. Node sert directement.
|
||||
|
||||
Ajouter un `.dockerignore` s'il n'existe pas :
|
||||
```
|
||||
node_modules
|
||||
.nuxt
|
||||
.output
|
||||
dist
|
||||
src
|
||||
.git
|
||||
*.md
|
||||
.planning
|
||||
```
|
||||
|
||||
**docker-compose.yml** (per D-14) : Modifier la ligne port Traefik :
|
||||
```yaml
|
||||
- 'traefik.http.services.portfolio.loadbalancer.server.port=3000' # was 80
|
||||
```
|
||||
Changer uniquement cette ligne. Conserver tout le reste intact (labels Traefik TLS, routeurs, redirections www).
|
||||
|
||||
Ajouter les variables d'environnement SMTP dans la section `environment` du service portfolio :
|
||||
```yaml
|
||||
environment:
|
||||
- TZ=Europe/Paris
|
||||
- NUXT_SMTP_HOST=${NUXT_SMTP_HOST}
|
||||
- NUXT_SMTP_USER=${NUXT_SMTP_USER}
|
||||
- NUXT_SMTP_PASS=${NUXT_SMTP_PASS}
|
||||
- NUXT_SMTP_TO=${NUXT_SMTP_TO}
|
||||
- NUXT_PUBLIC_GTAG_ID=${NUXT_PUBLIC_GTAG_ID}
|
||||
```
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd C:/Users/minit/Desktop/portfolio/portfolio && grep -q ".output/server/index.mjs" Dockerfile && grep -q "node:22-alpine" Dockerfile && grep -q "port=3000" docker-compose.yml && echo "PASS"</automated>
|
||||
</verify>
|
||||
<done>Dockerfile SSR multi-stage node:22-alpine avec .output/, docker-compose port 3000, variables env SMTP/GA4</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: GA4 production-only + formation redirect + cleanup</name>
|
||||
<files>nuxt.config.ts, app/pages/formation.vue</files>
|
||||
<action>
|
||||
**GA4 nuxt-gtag** (per D-15, INFRA-04) : Verifier/mettre a jour `nuxt.config.ts` pour que nuxt-gtag soit configure correctement. Le config existant a deja :
|
||||
```typescript
|
||||
gtag: {
|
||||
id: '',
|
||||
enabled: import.meta.env.NODE_ENV === 'production',
|
||||
},
|
||||
```
|
||||
Verifier que `runtimeConfig.public.gtag.id` est bien present (deja fait en Plan 01 pour SMTP). Le `NUXT_PUBLIC_GTAG_ID` sera injecte au runtime sans rebuild (per D-13). Rien a changer si deja correct — juste verifier.
|
||||
|
||||
**Page Formation** (per D-19) : La page formation est supprimee. Si `app/pages/formation.vue` existe comme stub, le remplacer par une redirection :
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
// D-19: Formation page removed from scope
|
||||
definePageMeta({
|
||||
middleware: () => navigateTo('/', { redirectCode: 301 })
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div />
|
||||
</template>
|
||||
```
|
||||
Si le fichier n'existe pas, le creer quand meme pour eviter les 404 sur d'anciens liens.
|
||||
|
||||
**Nettoyage :** NE PAS supprimer le dossier `src/` dans cette phase — il sert de reference et sera nettoye dans une future phase de maintenance. Supprimer uniquement `nginx.conf` s'il existe (plus utile avec le Dockerfile SSR).
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd C:/Users/minit/Desktop/portfolio/portfolio && grep -q "production" nuxt.config.ts && grep -q "navigateTo\|redirect" app/pages/formation.vue && echo "PASS"</automated>
|
||||
</verify>
|
||||
<done>GA4 nuxt-gtag actif en production via runtimeConfig, formation.vue redirige vers /, nginx.conf supprime si present</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<threat_model>
|
||||
## Trust Boundaries
|
||||
|
||||
| Boundary | Description |
|
||||
|----------|-------------|
|
||||
| Docker env vars -> runtimeConfig | Variables SMTP passees au container via docker-compose |
|
||||
|
||||
## STRIDE Threat Register
|
||||
|
||||
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|
||||
|-----------|----------|-----------|-------------|-----------------|
|
||||
| T-03-07 | Information Disclosure | docker-compose.yml | mitigate | Variables SMTP referencent ${VAR} pas de valeurs hardcodees — .env non commite |
|
||||
| T-03-08 | Information Disclosure | Dockerfile | mitigate | .dockerignore exclut .planning, .git, src, node_modules |
|
||||
</threat_model>
|
||||
|
||||
<verification>
|
||||
- `docker build -t portfolio .` complete sans erreur
|
||||
- `docker run --rm -p 3000:3000 portfolio` sert l'app sur http://localhost:3000
|
||||
- `curl http://localhost:3000/` retourne du HTML complet SSR
|
||||
- L'image Docker finale est < 300MB (node:22-alpine + .output seulement)
|
||||
- `/formation` redirige vers `/` avec status 301
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Dockerfile utilise node:22-alpine en 2 stages, copie .output/, lance node server/index.mjs (per D-12)
|
||||
- docker-compose port Traefik = 3000 (per D-14)
|
||||
- Variables env SMTP + GA4 passees via docker-compose environment
|
||||
- nuxt-gtag actif uniquement en production (per D-15)
|
||||
- formation.vue redirige vers / en 301 (per D-19)
|
||||
- .dockerignore exclut node_modules, .nuxt, .output, src, .git
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/03-pages-ship/03-04-SUMMARY.md`
|
||||
</output>
|
||||
Reference in New Issue
Block a user