` wrapper — the layout handles structure now.
grep -q "AppHeader" app/layouts/default.vue && grep -q "AppFooter" app/layouts/default.vue && grep -q "simple-icons:gitea" app/components/layout/AppFooter.vue && grep -q "useLocaleHead" app/app.vue && grep -q "NuxtLayout" app/app.vue && echo "PASS" || echo "FAIL"
- app/components/layout/AppFooter.vue contains `simple-icons:gitea` (not github)
- app/components/layout/AppFooter.vue contains `simple-icons:linkedin` and `simple-icons:fiverr`
- app/components/layout/AppFooter.vue contains `target="_blank"` and `rel="noopener noreferrer"`
- app/components/layout/AppFooter.vue contains `t('footer.copyright')`
- app/layouts/default.vue contains `` and ``
- app/layouts/default.vue contains ``
- app/app.vue contains `useLocaleHead({ addSeoAttributes: true })`
- app/app.vue contains `` wrapping ``
- app/app.vue does NOT contain ``
AppFooter renders copyright + Gitea/LinkedIn/Fiverr social icons. Default layout wraps header + slot + footer. app.vue uses NuxtLayout and injects global hreflang/canonical via useLocaleHead().
## Trust Boundaries
| Boundary | Description |
|----------|-------------|
| External links (footer) | Social icon links open external URLs in new tabs |
## STRIDE Threat Register
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|-----------|----------|-----------|-------------|-----------------|
| T-02-04 | Tampering | External social links | mitigate | All external links use `rel="noopener noreferrer"` to prevent reverse tabnabbing |
| T-02-05 | Spoofing | Locale switching | accept | setLocale only accepts 'fr' or 'en' — constrained by i18n config, no injection risk |
- `pnpm dev` starts and renders header + footer on localhost:3000
- Language toggle switches between FR/EN URLs
- Theme toggle switches dark/light classes
- Mobile hamburger opens UDrawer
- `curl http://localhost:3000` returns HTML with `
- Header sticky with nav links, FR/EN toggle, dark/light toggle, mobile drawer
- Footer shows copyright and 3 social icon links
- Default layout renders header + page content + footer
- app.vue injects global hreflang/canonical metadata
- All interactive elements have focus rings and ARIA labels