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,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>
|
||||
Reference in New Issue
Block a user