Files
portfolio/.planning/phases/02-ssr-shell/02-03-PLAN.md
T
kayjaydee c8dac9ac88 fix: update portfolio branding to "Killian' DAL-CIN" across all documentation and components
- Corrected the name in various files including CLAUDE.md, README.md, and configuration files to reflect the updated branding.
- Ensured consistency in the use of the new name throughout the project, enhancing brand identity.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 19:54:46 +02:00

8.0 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
02-ssr-shell 03 execute 2
02-01
app/pages/index.vue
app/pages/projects.vue
app/pages/about.vue
app/pages/contact.vue
app/pages/fiverr.vue
app/pages/formation.vue
true
SEO-01
SEO-02
SEO-04
truths artifacts key_links
Every route has unique title, description, og:title, og:description in SSR HTML
Homepage includes JSON-LD Person + ProfessionalService schema
Every route has og:image with absolute URL
curl output for each route contains <title> and og:description meta tag
path provides contains
app/pages/index.vue Homepage with SEO metadata and JSON-LD useSeoMeta
path provides contains
app/pages/projects.vue Projects stub page with SEO metadata useSeoMeta
from to via pattern
app/pages/index.vue app/locales/fr.json t('seo.home.title') for localized SEO seo.home.title
from to via pattern
app/pages/index.vue JSON-LD useHead script tag application/ld+json
Add per-route SEO metadata (useSeoMeta) and JSON-LD structured data to all page stubs.

Purpose: Every route returns correct, unique, localized SEO tags in server-rendered HTML — verifiable by curl. Output: 6 page files with useSeoMeta(), homepage with JSON-LD, all with og:image.

<execution_context> @/.claude/get-shit-done/workflows/execute-plan.md @/.claude/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/phases/02-ssr-shell/02-CONTEXT.md @.planning/phases/02-ssr-shell/02-RESEARCH.md @.planning/phases/02-ssr-shell/02-UI-SPEC.md @.planning/phases/02-ssr-shell/02-01-SUMMARY.md Task 1: Per-route SEO metadata on all page stubs app/pages/index.vue, app/pages/projects.vue, app/pages/about.vue, app/pages/contact.vue, app/pages/fiverr.vue, app/pages/formation.vue - app/pages/index.vue (current stub — will be enhanced) - app/locales/fr.json (verify seo.* keys exist) - .planning/phases/02-ssr-shell/02-RESEARCH.md (Pattern 3: useSeoMeta per route; Pattern 4: JSON-LD) - .planning/phases/02-ssr-shell/02-UI-SPEC.md (SEO Contract table) - src/config/site.ts (siteConfig.seo.organization for JSON-LD schema data; url: https://killiandalcin.fr) Update each page stub to include `useSeoMeta()` with localized metadata. Pages remain stubs (minimal template content) — Phase 3 fills real content.

Pattern for every page (example: projects.vue):

<script setup lang="ts">
const { t } = useI18n()

useSeoMeta({
  title: () => t('seo.projects.title'),
  description: () => t('seo.projects.description'),
  ogTitle: () => t('seo.projects.title'),
  ogDescription: () => t('seo.projects.description'),
  ogImage: 'https://killiandalcin.fr/og-image.png',
  ogImageWidth: 1200,
  ogImageHeight: 630,
  ogType: 'website',
})
</script>

<template>
  <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
    <h1 class="text-2xl font-bold">{{ t('nav.projects') }}</h1>
    <p class="text-gray-600 dark:text-gray-400 mt-4">Phase 3 content placeholder</p>
  </div>
</template>

Apply this pattern to all 6 pages using their respective seo.{page}.title and seo.{page}.description keys:

  • index.vue → seo.home.*
  • projects.vue → seo.projects.*
  • about.vue → seo.about.*
  • contact.vue → seo.contact.*
  • fiverr.vue → seo.fiverr.*
  • formation.vue → seo.formation.*

All pages use ogImage: 'https://killiandalcin.fr/og-image.png' (per user decision: static image, no nuxt-og-image).

Homepage (index.vue) ADDITIONALLY gets JSON-LD (per D-11, SEO-02):

useHead({
  script: [
    {
      type: 'application/ld+json',
      innerHTML: JSON.stringify({
        '@context': 'https://schema.org',
        '@graph': [
          {
            '@type': 'Person',
            name: 'Killian' DAL-CIN',
            url: 'https://killiandalcin.fr',
            jobTitle: 'Developpeur Full Stack Freelance',
            email: 'contact@killiandalcin.fr',
            sameAs: [
              'https://linkedin.com/in/killian-dal-cin',
              'https://www.fiverr.com/users/mr_kayjaydee',
              'https://gitea.kamisama.ovh/kayjaydee',
            ],
          },
          {
            '@type': 'ProfessionalService',
            name: 'Killian' DAL-CIN - Developpeur Full Stack',
            url: 'https://killiandalcin.fr',
            logo: 'https://killiandalcin.fr/images/logo.webp',
            priceRange: '$$$',
            areaServed: 'Worldwide',
          },
        ],
      }),
    },
  ],
})

Create pages that do not yet exist (projects.vue, about.vue, contact.vue, fiverr.vue, formation.vue) as new files. Update existing index.vue.

Each stub page template should have:

  • <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12"> wrapper (per D-16)
  • An <h1> using the nav translation key
  • A placeholder paragraph grep -q "useSeoMeta" app/pages/index.vue && grep -q "application/ld+json" app/pages/index.vue && grep -q "useSeoMeta" app/pages/projects.vue && grep -q "useSeoMeta" app/pages/about.vue && grep -q "useSeoMeta" app/pages/contact.vue && grep -q "useSeoMeta" app/pages/fiverr.vue && grep -q "useSeoMeta" app/pages/formation.vue && grep -q "og-image.png" app/pages/index.vue && echo "PASS" || echo "FAIL" <acceptance_criteria>
    • All 6 page files exist under app/pages/
    • Every page contains useSeoMeta with title, description, ogTitle, ogDescription, ogImage
    • ogImage value is https://killiandalcin.fr/og-image.png on every page
    • index.vue contains application/ld+json with Person and ProfessionalService
    • index.vue JSON-LD contains sameAs array with LinkedIn, Fiverr, Gitea URLs
    • Each page uses localized seo keys: t('seo.home.title'), t('seo.projects.title'), etc.
    • Each page template has max-w-7xl mx-auto wrapper
    • npx nuxi typecheck passes </acceptance_criteria> All 6 routes have unique, localized SEO metadata via useSeoMeta(). Homepage includes JSON-LD with Person + ProfessionalService schema. Every page has og:image with absolute URL.

<threat_model>

Trust Boundaries

Boundary Description
SEO meta tags Server-rendered meta tags include user-controlled translation values

STRIDE Threat Register

Threat ID Category Component Disposition Mitigation Plan
T-02-06 Injection JSON-LD innerHTML mitigate JSON.stringify() escapes special characters; no user input in JSON-LD — all values are hardcoded constants
T-02-07 Information Disclosure og:image URL accept Public URL pointing to public image — no sensitive data
</threat_model>
- `pnpm dev` then `curl http://localhost:3000` returns HTML containing `