- 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>
12 KiB
phase, slug, status, shadcn_initialized, preset, created
| phase | slug | status | shadcn_initialized | preset | created |
|---|---|---|---|---|---|
| 2 | ssr-shell | draft | false | none | 2026-04-08 |
Phase 2 — UI Design Contract: SSR Shell
Visual and interaction contract for Phase 2: SSR Shell. Generated by gsd-ui-researcher, verified by gsd-ui-checker.
Design System
| Property | Value |
|---|---|
| Tool | Nuxt UI v3 (not shadcn — shadcn gate not applicable) |
| Preset | not applicable |
| Component library | Nuxt UI v3 (@nuxt/ui) — use native components exclusively; custom only when Nuxt UI has no equivalent |
| Icon library | Nuxt Icon (bundled with @nuxt/ui) — Heroicons set (heroicons:) for theme toggle (sun/moon) and social icons (GitHub, LinkedIn, Fiverr via simple-icons:) |
| Font | Inter (system stack fallback: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif) — sourced: --font-family-sans from existing main.css |
Source: D-17, D-18, D-20 from 02-CONTEXT.md. No components.json found; shadcn gate skipped.
Spacing Scale
Declared values (multiples of 4 only). Mapped to Tailwind v4 / Nuxt UI tokens:
| Token | Value | Usage |
|---|---|---|
| xs | 4px (p-1 / gap-1) | Icon gaps, inline padding between icon and label |
| sm | 8px (p-2 / gap-2) | Compact element spacing, icon button padding |
| md | 16px (p-4 / gap-4) | Default element spacing, nav link padding |
| lg | 24px (p-6 / gap-6) | Header internal padding, footer padding |
| xl | 32px (p-8 / gap-8) | Layout horizontal gutters |
| 2xl | 48px (py-12) | Not used in Phase 2 (no content sections) |
| 3xl | 64px (py-16) | Not used in Phase 2 (no content sections) |
Exceptions:
- Touch targets (hamburger button, lang toggle, theme toggle): minimum 44px × 44px — use
min-w-11 min-h-11to comply with WCAG 2.5.5 - Content max-width:
max-w-7xl(1280px) centered withmx-auto px-4 sm:px-6 lg:px-8— from D-16
Source: D-16 from 02-CONTEXT.md; existing spacing tokens in src/assets/main.css.
Typography
Phase 2 covers only the header and footer — no page content. Typography scope is limited to nav labels, logo text, footer copyright, and toggle labels.
| Role | Size | Weight | Line Height |
|---|---|---|---|
| Body / nav link | 16px (text-base / 1rem) | 400 (normal) | 1.5 |
| Label / small copy | 14px (text-sm / 0.875rem) | 400 (normal) | 1.5 |
| Logo name | 18px (text-lg / 1.125rem) | 600 (semibold) | 1.2 |
| Footer copyright | 14px (text-sm / 0.875rem) | 400 (normal) | 1.5 |
Rules:
- Maximum 2 font weights used: 400 (regular) and 600 (semibold)
- No italic, no uppercase transforms on nav links
- Logo name "Killian" uses semibold to anchor visual identity
Source: Existing --font-size-base, --font-size-sm, --font-weight-normal, --font-weight-semibold from src/assets/main.css.
Color
Light Mode
| Role | Value | Usage |
|---|---|---|
| Dominant (60%) | #ffffff |
Page background, header background |
| Secondary (30%) | #f3f4f6 (gray-100) |
Footer background band, subtle separators |
| Accent (10%) | #85cb85 |
CTA buttons, active nav link underline, hover states on nav links, social icon hover |
| Destructive | #ef4444 |
Not used in Phase 2 — no destructive actions |
Dark Mode (default for new visitors — D-08)
| Role | Value | Usage |
|---|---|---|
| Dominant (60%) | #111827 (gray-900) |
Page background, header background |
| Secondary (30%) | #1f2937 (gray-800) |
Footer background band, drawer background |
| Accent (10%) | #a3d6a3 |
CTA buttons, active nav link underline, hover states on nav links, social icon hover (lightened for dark bg) |
| Destructive | #ef4444 |
Not used in Phase 2 |
Accent Reserved For (explicit list)
- Active nav link — bottom border/underline indicator
- Nav link hover state — text color change
- Language toggle hover state — text color
- Theme toggle icon hover state — icon color
- Social icon links in footer — hover color
Accent is NOT used for: passive text, borders, backgrounds, icons in default (non-hover) state.
WCAG Compliance
- Dark mode body text (#f9fafb on #111827): contrast ratio ~18:1 — PASS
- Accent #a3d6a3 on #111827 for interactive labels: contrast ratio ~6.2:1 — PASS (4.5:1 minimum)
- Accent #85cb85 on #ffffff for interactive labels: contrast ratio ~2.5:1 — FAIL for text; use as decoration/border only in light mode. Nav link text stays on
--text-primary(#111827), accent applied as underline decoration only - Never use red/green alone as meaning — always pair with icon or text label (D-19)
Source: D-17, D-18, D-19 from 02-CONTEXT.md; existing CSS variables from src/assets/main.css.
Component Inventory
Components delivered in this phase only:
AppHeader (COMP-05)
- Container:
<header>withposition: sticky; top: 0; z-index: 1020 - Inner wrapper:
max-w-7xl mx-auto px-4 sm:px-6 lg:px-8— height 64px (h-16) - Layout: flex row,
items-center justify-between - Left: Logo (40×40px image + "Killian" text)
- Center: Desktop nav links (
hidden md:flex gap-6) usingUNavigationMenuor native<nav>with<NuxtLink>— active link usesaria-current="page"+ accent underline - Right: LanguageToggle (FR/EN text button) + ThemeToggle (icon button) + HamburgerButton (mobile only,
md:hidden) - Background:
bg-white dark:bg-gray-900with subtle bottom borderborder-b border-gray-200 dark:border-gray-800
LanguageToggle (inside COMP-05)
- Renders as a
<button>displaying current locale code in uppercase: "FR" or "EN" - Click switches locale (D-04 — text toggle, no dropdown, no flags)
- Size: minimum 44×44px touch target
- Style: ghost button, no background. Accent color on hover.
ThemeToggle (inside COMP-05)
- Renders
heroicons:sun(light mode active) orheroicons:moon(dark mode active) - Icon size: 20px (w-5 h-5)
- Click toggles
@nuxtjs/color-mode(D-09) - Transition:
transition-colors duration-300on icon swap — no flash - Size: minimum 44×44px touch target
MobileDrawer (inside COMP-05)
- Uses
UDrawercomponent from Nuxt UI v3 (D-02) - Opens from left, triggered by hamburger icon (
heroicons:bars-3) - Close icon:
heroicons:x-markinside drawer - Contains: nav links (stacked, full-width) + LanguageToggle + ThemeToggle
- Overlay:
bg-black/50backdrop
AppFooter (COMP-06)
- Single band:
py-6 bg-gray-100 dark:bg-gray-800 - Layout: flex row on md+, flex column on mobile —
items-center justify-between gap-4 - Left: copyright text — "© 2026 Killian' DAL-CIN"
- Right: social icon links — GitHub (
simple-icons:github), LinkedIn (simple-icons:linkedin), Fiverr (simple-icons:fiverr) - Icon size: 20px (w-5 h-5). Hover: accent color with
transition-colors duration-150 - All links open in
_blankwithrel="noopener noreferrer"andaria-label
Interaction States
All interactive elements must implement all four states:
| Element | Default | Hover | Focus | Active |
|---|---|---|---|---|
| Nav link | text-gray-700 dark:text-gray-300 |
accent color text | focus-visible:ring-2 ring-primary-500 ring-offset-2 |
accent underline |
| Active nav link | accent underline border-b-2 border-primary-500 |
— | same focus ring | — |
| Language toggle | text-gray-700 dark:text-gray-300 font-medium |
accent color | focus ring | — |
| Theme toggle icon | text-gray-600 dark:text-gray-400 |
accent color | focus ring | — |
| Social icon | text-gray-500 dark:text-gray-400 |
accent color | focus ring | scale-110 |
| Hamburger button | text-gray-700 dark:text-gray-300 |
accent color | focus ring | — |
Focus ring spec: outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 — keyboard navigation only, never on click.
Copywriting Contract
Phase 2 scope: header nav labels, footer copyright, mobile drawer, language/theme toggles, ARIA labels.
| Element | Copy (FR) | Copy (EN) |
|---|---|---|
| Logo aria-label | "Killian' DAL-CIN — Développeur Full Stack — Retour à l'accueil" | "Killian' DAL-CIN — Full Stack Developer — Back to homepage" |
| Nav: Home | "Accueil" | "Home" |
| Nav: Projects | "Projets" | "Projects" |
| Nav: About | "À propos" | "About" |
| Nav: Contact | "Contact" | "Contact" |
| Nav: Fiverr | "Fiverr" | "Fiverr" |
| Nav: Formation | "Formation" | "Training" |
| Hamburger open aria-label | "Ouvrir le menu de navigation" | "Open navigation menu" |
| Hamburger close aria-label | "Fermer le menu de navigation" | "Close navigation menu" |
| Drawer close button aria-label | "Fermer le menu" | "Close menu" |
| Language toggle aria-label | "Changer la langue — actuellement Français" | "Change language — currently English" |
| Theme toggle aria-label (dark) | "Activer le mode clair" | "Switch to light mode" |
| Theme toggle aria-label (light) | "Activer le mode sombre" | "Switch to dark mode" |
| Footer copyright | "© 2026 Killian' DAL-CIN" | "© 2026 Killian' DAL-CIN" |
| GitHub icon aria-label | "GitHub de Killian' DAL-CIN (nouvelle fenêtre)" | "Killian' DAL-CIN on GitHub (opens in new tab)" |
| LinkedIn icon aria-label | "LinkedIn de Killian' DAL-CIN (nouvelle fenêtre)" | "Killian' DAL-CIN on LinkedIn (opens in new tab)" |
| Fiverr icon aria-label | "Fiverr de Killian' DAL-CIN (nouvelle fenêtre)" | "Killian' DAL-CIN on Fiverr (opens in new tab)" |
Destructive confirmation: none — Phase 2 has no destructive actions. Empty state: none — Phase 2 has no data-driven content. Error state: none — Phase 2 has no form submissions or async data.
Source: D-04, D-05, COMP-05, COMP-06 from 02-CONTEXT.md. Translations to be added to fr.json / en.json under keys nav.*, footer.*, a11y.*.
SEO Contract (server-rendered metadata)
Each route in Phase 2 must include the following in SSR HTML output (verified by curl):
| Tag | Requirement |
|---|---|
<title> |
Per-route via useSeoMeta({ title }) |
<meta name="description"> |
Per-route, max 160 chars |
<meta property="og:title"> |
Same as title |
<meta property="og:description"> |
Same as description |
<meta property="og:image"> |
Absolute URL via nuxt-og-image (D-12) |
<link rel="canonical"> |
Absolute URL for current locale route |
<link rel="alternate" hreflang="fr"> |
FR URL |
<link rel="alternate" hreflang="en"> |
EN URL |
| JSON-LD script | Homepage only: Person + ProfessionalService schema (D-11) |
Phase 2 uses placeholder routes (no real pages yet) — SEO metadata is wired but content is minimal stubs until Phase 3 fills pages.
Registry Safety
| Registry | Blocks Used | Safety Gate |
|---|---|---|
| Nuxt UI v3 (@nuxt/ui) | UDrawer, UNavigationMenu, UButton, UIcon | Built-in module — no registry vetting required |
| shadcn | none | Not used |
| Third-party | none | Not applicable |
No third-party component registries are used in this phase. All components come from @nuxt/ui which is installed as a verified Nuxt module.
Implementation Notes for Executor
- No components.json — shadcn is not used. All component imports are via Nuxt UI v3 auto-imports (
UDrawer,UButton, etc.) or native HTML. - app.config.ts must define primary color token mapping to
#85cb85(light) /#a3d6a3(dark) using Nuxt UI v3 token format. - @nuxtjs/color-mode must be added to
nuxt.config.tsmodules for FOUC-free dark mode persistence. Default:dark. - nuxt-og-image must be added to
nuxt.config.tsmodules (D-12 advanced from v2). - Header
z-indexmust be1020(z-sticky) to sit above page content but below modals (Phase 3). - The drawer overlay must trap focus while open (keyboard accessibility).
- Lang toggle button must call
setLocale()from@nuxtjs/i18ncomposable.
Checker Sign-Off
- Dimension 1 Copywriting: PASS
- Dimension 2 Visuals: PASS
- Dimension 3 Color: PASS
- Dimension 4 Typography: PASS
- Dimension 5 Spacing: PASS
- Dimension 6 Registry Safety: PASS
Approval: pending
Phase: 02-ssr-shell UI-SPEC generated: 2026-04-08