Files
ResumeSite/docs/spec/SEO_SPEC.md
2026-07-03 21:07:25 +02:00

3.7 KiB
Raw Permalink Blame History

SEO_SPEC.md

1. Goals & reality check

Primary discovery is direct (links from applications/LinkedIn/CV), not organic search. SEO effort therefore targets: (1) branded queries ("Connor Babbington developer") ranking the new site #1 in both languages, (2) clean link-preview cards everywhere recruiters paste URLs (Slack/Teams/LinkedIn/ATS), (3) not losing the existing domain's standing during the WordPress → new-site cutover.

2. Per-page metadata (both locales)

  • Titles (patterns fixed in CONTENT_STRATEGY §7): home Connor Babbington — Systems Developer (.NET, React) · Tønsberg, Norway / … Systemutvikler … · Tønsberg; inner pages <Page> · Connor Babbington. ≤ 60 chars target.
  • Descriptions: handwritten per page per locale, ≤ 155 chars, answer who/what/where. Stored in page-meta content (DATA_MODEL §6), length CI-checked.
  • Canonical: self-referencing per locale page. hreflang: en, nb, x-default → en emitted from the slug map on every page — the twin-URL contract guarantees correctness; CI tests hreflang reciprocity.
  • robots: index,follow everywhere except 404/colophon-draft states; robots.txt allows all + sitemap pointer.

3. Structured data (JSON-LD, build-time)

Page Schema
Home (both locales) Person: name, jobTitle "Systems Developer"/"Systemutvikler", address (locality Tønsberg, country NO), email, sameAs [LinkedIn, git.cesnimda.uk], knowsLanguage [en, nb], knowsAbout [C#, .NET, React, Docker, …]
Case studies CreativeWork (subtype SoftwareApplication where honest — JobTrack yes, InboxIntel as SoftwareSourceCode): name, description, author → Person, programmingLanguage, dateModified
CV hub Person + subjectOf links to CV files
All WebSite + BreadcrumbList on nested pages

Builders are typed utilities with unit tests (TECH_SPEC §9.2) — malformed JSON-LD is worse than none.

  • Per-page, per-locale OG: og:locale (en_GB/nb_NO) + og:locale:alternate, title/description mirroring meta, og:type profile (home) / article (case studies).
  • OG images pre-generated at build (one template per page kind, design-system styled: dark surface, name/page title, role line, trace motif, monogram; case studies add project name + stack line). 1200×630 PNG, per locale. Twitter/X summary_large_image tags mirrored.
  • This directly fixes the current site's empty og:title embarrassment noted in Phase 1 research.

5. Sitemaps

  • Build-generated sitemap index → one sitemap per locale; entries carry xhtml:link alternates (belt-and-braces with hreflang tags); lastmod from git commit dates of content files.
  • Submitted via Search Console (both properties/domains as relevant) at launch; the old WP sitemap URLs left to 404→410 after cutover inventory.

6. Migration / cutover protection

  1. Inventory before cutover (Phase 3 task): crawl current WP site, list indexed URLs (site:cesnimda.co.uk), old anchors, and any URL known to be printed/shared (esp. /Linkedin redirect — preserved per ROUTING_SPEC).
  2. 301 map for anything with inbound value; 410 for WP cruft (/feed/, /wp-json/, /comments/…). Never soft-404.
  3. Keep domain, keep HTTPS, no www/apex flip during migration (site currently canonicalises to apex — retain).
  4. Verify: Search Console coverage watch for 4 weeks post-launch; link-preview spot checks in LinkedIn/Slack debuggers.

7. Performance & crawlability as SEO

Static HTML, content not JS-gated (crawler parity guaranteed by architecture), CWV budgets in CI (LCP < 1.8 s, CLS < 0.02) — the technical-SEO checklist is mostly satisfied by construction; this spec adds only the markup/meta layer above.