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:
2026-04-08 18:25:28 +02:00
parent 049b1f0f81
commit e5e14ef362
5 changed files with 979 additions and 2 deletions
@@ -0,0 +1,233 @@
---
phase: 03-pages-ship
plan: 03
type: execute
wave: 2
depends_on: ["03-01"]
files_modified:
- app/pages/about.vue
- app/pages/contact.vue
- app/pages/fiverr.vue
- app/error.vue
autonomous: true
requirements:
- PAGE-04
- PAGE-05
- PAGE-06
- PAGE-08
must_haves:
truths:
- "About page affiche bio + tech stack badges par categorie"
- "Contact page affiche formulaire 3 champs + infos contact + reseaux sociaux"
- "Fiverr page affiche hero + service cards + FAQ accordion + CTA"
- "404 page affiche code erreur + message + bouton retour accueil"
artifacts:
- path: "app/pages/about.vue"
provides: "Page about avec bio et tech stack"
- path: "app/pages/contact.vue"
provides: "Page contact avec formulaire"
- path: "app/pages/fiverr.vue"
provides: "Page fiverr avec services"
- path: "app/error.vue"
provides: "Page 404 custom"
key_links:
- from: "app/pages/contact.vue"
to: "app/components/ContactForm.vue"
via: "auto-import"
pattern: "ContactForm"
- from: "app/pages/fiverr.vue"
to: "app/components/sections/FAQSection.vue"
via: "auto-import"
pattern: "FAQSection"
---
<objective>
Construire les 4 pages restantes : About, Contact, Fiverr, et error.vue (404). Ces pages consomment les composants partages du Plan 01.
Purpose: Complete le portfolio avec toutes les pages necessaires — About pour la credibilite, Contact pour la conversion, Fiverr pour les services, 404 pour l'UX.
Output: 4 pages fonctionnelles.
</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-01-SUMMARY.md
@src/views/AboutPage.vue
@src/views/ContactPage.vue
@src/views/FiverrPage.vue
@app/data/techstack.ts
@app/data/faq.ts
@src/config/site.ts
<interfaces>
Composants disponibles (auto-importes, crees en Plan 01):
- ContactForm — pas de props (formulaire autonome avec Zod + useToast)
- FAQSection — props: faqs (FAQ[]), title, subtitle
- TechBadge — props: tech (Technology | string), showLevel?, showImage?
From app/data/site.ts (cree en Plan 01):
```typescript
export const siteConfig: SiteConfig
// siteConfig.contact: { email, phone, location }
// siteConfig.social: SocialLink[]
// siteConfig.fiverr: { profileUrl, services: FiverrService[] }
```
From app/data/techstack.ts:
```typescript
export const techStack: TechStack
// .programming, .front, .database, .devtools, .operating_systems, .socials
```
From app/data/faq.ts:
```typescript
export const homeFAQs: FAQ[]
```
</interfaces>
</context>
<tasks>
<task type="auto">
<name>Task 1: Pages About + Contact</name>
<files>app/pages/about.vue, app/pages/contact.vue</files>
<action>
**about.vue** (per D-16, D-17, PAGE-04) : Migrer depuis src/views/AboutPage.vue.
1. Section hero : titre `t('about.title')`, sous-titre, intro content (2 paragraphes bio)
2. Section Skills : 4 categories tech (programming, front, database, devtools) en grille 2x2 avec `UCard`. Chaque card : icone, titre categorie, grille `TechBadge` avec `showLevel`. Section OS separee en bas.
3. Section Approach : 4 cards (performance, architecture, quality, collaboration) avec `UCard`, icones lucide.
4. Section CTA : titre + 2 boutons (Contact, Projets) via `UButton`.
5. `useSeoMeta()` avec titre/description about.
**contact.vue** (per D-08, D-10, D-16, PAGE-05) : Migrer depuis src/views/ContactPage.vue.
1. Section hero : titre `t('contact.title')`, sous-titre, stats (24-48h response, 100% satisfaction, Remote)
2. Layout 2 colonnes :
- Colonne gauche : `<ContactForm />` (auto-importe du Plan 01, gere tout seul — Zod, $fetch, UToast)
- Colonne droite : Infos contact (`UCard` avec email cliquable, telephone, localisation depuis `siteConfig.contact`) + Reseaux sociaux (`UCard` avec liens `siteConfig.social` — icones pour Gitea/LinkedIn/Discord)
3. Section FAQ en bas : 3 cards info (temps reponse, types projets, collaboration) avec `UCard`.
4. `useSeoMeta()` specifique contact.
Importer `siteConfig` depuis `~/data/site`.
</action>
<verify>
<automated>cd C:/Users/minit/Desktop/portfolio/portfolio && grep -q "TechBadge" app/pages/about.vue && grep -q "techStack" app/pages/about.vue && grep -q "ContactForm" app/pages/contact.vue && grep -q "siteConfig" app/pages/contact.vue && echo "PASS"</automated>
</verify>
<done>About page avec bio + 5 categories tech stack badges, Contact page avec ContactForm + infos contact + reseaux sociaux</done>
</task>
<task type="auto">
<name>Task 2: Page Fiverr avec hero + services + FAQ accordion + CTA</name>
<files>app/pages/fiverr.vue</files>
<action>
Migrer depuis src/views/FiverrPage.vue (per D-18, PAGE-06).
1. **Script setup** : Importer `siteConfig` depuis `~/data/site`. Computed `services` = `siteConfig.fiverr.services`. Computed `heroStats` avec nombre services dispo + rating "5 etoiles".
2. **Section Hero** : titre `t('fiverr.title')`, sous-titre, stats (services count, rating), bouton CTA `UButton` vers `siteConfig.fiverr.profileUrl` (external link, target blank).
3. **Section Services** : grille de service cards. Pour chaque service dans `siteConfig.fiverr.services`, utiliser `UCard` avec :
- Image service via `NuxtImg :src="service.image"`
- Badge prix : `t('fiverr.pricing.startingAt') + ' ' + service.price`
- Badge statut : "Disponible" (vert) si url !== '#', "Bientot" (jaune) sinon
- Titre et description via `t('fiverr.serviceData.${service.id}.title/description')`
- Features liste via i18n (recuperer du fichier de traduction comme dans src/views/FiverrPage.vue)
- Bouton commander / en savoir plus
4. **Section FAQ** (per D-18) : Utiliser `<FAQSection>` du Plan 01 avec les FAQs fiverr. Creer un array computed de FAQ fiverr depuis les cles i18n `fiverr.faq.*` si elles existent, sinon reutiliser `homeFAQs`.
5. **Section CTA finale** : titre `t('fiverr.cta.title')`, sous-titre, bouton vers profil Fiverr.
6. `useSeoMeta()` specifique fiverr.
</action>
<verify>
<automated>cd C:/Users/minit/Desktop/portfolio/portfolio && grep -q "siteConfig" app/pages/fiverr.vue && grep -q "fiverr" app/pages/fiverr.vue && grep -q "FAQSection\|UAccordion" app/pages/fiverr.vue && echo "PASS"</automated>
</verify>
<done>Page Fiverr avec hero stats, service cards, FAQ accordion UAccordion, CTA vers profil Fiverr</done>
</task>
<task type="auto">
<name>Task 3: Page 404 (error.vue)</name>
<files>app/error.vue</files>
<action>
Creer `app/error.vue` (per D-20, PAGE-08). IMPORTANT : dans `app/`, PAS dans `app/pages/` (per RESEARCH.md Pitfall 6).
Implementation exacte du RESEARCH.md Pattern 5 :
```vue
<script setup lang="ts">
import type { NuxtError } from '#app'
const props = defineProps<{ error: NuxtError }>()
const { t } = useI18n()
function handleError() {
clearError({ redirect: '/' })
}
</script>
<template>
<div class="min-h-screen flex flex-col items-center justify-center gap-6 px-4">
<h1 class="text-8xl font-bold text-primary">{{ error.statusCode }}</h1>
<p class="text-xl text-gray-500 dark:text-gray-400 text-center max-w-md">
{{ error.statusCode === 404 ? t('error.notFound') : t('error.generic') }}
</p>
<UButton size="lg" @click="handleError">
{{ t('error.backHome') }}
</UButton>
</div>
</template>
```
Ajouter les cles i18n manquantes si necessaire : `error.notFound` ("Page introuvable"), `error.generic` ("Une erreur est survenue"), `error.backHome` ("Retour a l'accueil") dans les fichiers de traduction FR/EN. Si les cles n'existent pas encore, les ajouter dans `i18n/locales/fr.json` et `i18n/locales/en.json`.
</action>
<verify>
<automated>cd C:/Users/minit/Desktop/portfolio/portfolio && test -f app/error.vue && grep -q "clearError" app/error.vue && grep -q "statusCode" app/error.vue && echo "PASS"</automated>
</verify>
<done>error.vue dans app/ avec affichage code erreur, message i18n, bouton retour accueil via clearError</done>
</task>
</tasks>
<threat_model>
## Trust Boundaries
| Boundary | Description |
|----------|-------------|
| Aucune nouvelle | Les pages About/Fiverr/404 ne traitent pas de donnees utilisateur. Contact est gere par ContactForm du Plan 01. |
## STRIDE Threat Register
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|-----------|----------|-----------|-------------|-----------------|
| T-03-06 | Information Disclosure | contact.vue | accept | email/telephone affiches publiquement — voulu par le proprietaire du site |
</threat_model>
<verification>
- `npx nuxi dev` puis naviguer vers `/about` — bio + 5 categories tech visible
- `/contact` — formulaire 3 champs fonctionnel + infos contact visibles
- `/fiverr` — 4 services, FAQ accordion, boutons CTA
- `/une-page-inexistante` — page 404 custom avec bouton retour
- `curl http://localhost:3000/about` — HTML complet avec meta tags
</verification>
<success_criteria>
- About affiche bio + tech stack par categorie avec TechBadge (per D-17)
- Contact affiche ContactForm (3 champs) + infos contact + reseaux (per D-08)
- Fiverr affiche hero + services + FAQ accordion + CTA (per D-18)
- error.vue dans app/ (pas pages/), affiche 404, bouton clearError (per D-20)
- Toutes les pages ont useSeoMeta()
</success_criteria>
<output>
After completion, create `.planning/phases/03-pages-ship/03-03-SUMMARY.md`
</output>