SEO is a feature, not an afterthought.
Most bespoke systems we inherit have SEO bolted on at the end. They never recover. Here's what shipping SEO-first actually looks like, the architectural decisions it forces, and the audit we now run on every new project.
Every system we get asked to rescue has the same story. Phase one was about features. Phase two was about scale. SEO was going to be "phase three". Phase three never happened, and now their organic traffic is a flat line on the dashboard. We see this maybe four or five times a year — usually a year or two after launch, when the founder finally checks Search Console and realises Google barely knows the site exists.
Retrofitting SEO into a system that wasn't built for it is one of the most expensive engineering projects we get asked to quote. The alternative — designing for it on day one — costs nothing extra. It just requires the team to take it seriously before launch, not after.
What SEO-first actually means
- 01Server-rendered HTML for every page that should rank. JavaScript-rendered content is a tax on every crawler.
- 02Semantic structure: one H1, hierarchical H2 / H3s, real <article>, <section>, <nav>, <main> tags. Screen readers and crawlers both win.
- 03Meta titles and descriptions specified per route — never the same boilerplate across the site.
- 04OpenGraph and Twitter card tags on every page that might get shared.
- 05A real sitemap, real canonical URLs, and a robots.txt that actually reflects what you want indexed.
- 06Structured data (schema.org JSON-LD) for content that maps to recognised types — articles, products, events, recipes.
- 07Fast loading. Core Web Vitals is a ranking factor; speed correlates with crawl budget too.
- 08Clean URLs without query-string sprawl. /products/widget-name is better than /shop?id=1432.
- 09Internal linking that reflects the actual information architecture, not the navigation menu.
The audit we run on every new project
| Check | What we look for | Why |
|---|---|---|
| Server-rendered HTML | View source contains real content, not just <div id="app"></div> | Crawlers index the rendered DOM, but quality and crawl budget reward true SSR |
| Unique meta titles | Every route has a per-page <title> tag specified | Default-everywhere titles cap how the page can rank |
| Unique meta descriptions | Per-route descriptions; never duplicated | Drives click-through from search results |
| Canonical tags | <link rel="canonical"> on every page | Prevents duplicate-content penalties from URL variations |
| Sitemap.xml | Submitted to Search Console, kept current | Tells crawlers what to look at |
| Robots.txt | Reflects production reality, no accidental Disallow: / | Mistakes here can de-index whole sites |
| Structured data | JSON-LD for the content types that have schemas | Enables rich results in SERPs |
| Core Web Vitals | LCP < 2.5s, CLS < 0.1, INP < 200ms on real devices | Direct ranking factor since 2021 |
| HTTPS | Site fully on HTTPS, no mixed content | Ranking factor; trust factor |
| Mobile-friendly | Mobile-first indexing means mobile is the primary crawl target | Google now indexes the mobile version of your site, not desktop |
What it changes about the build
It changes the framework choice (we lean toward Nuxt for exactly this reason; Next, Astro, and Remix all qualify). It changes how you structure your routes — every page that should rank gets its own URL and its own server-rendered output. It changes whether you fetch on the client or the server. It changes how you write your component tree, because the markup the bot sees is the markup that ships.
It also changes the meeting structure. Marketing has to be in the architecture review. SEO is downstream of decisions made by engineers in week one. If marketing only joins in week twelve to ask 'is this SEO-friendly?', the answer is going to be 'mostly no, and the fix is expensive'.
Retrofitting SEO into a single-page app is one of those projects that quietly costs a small site three months and a big site twelve. Doing it on day one costs nothing — it's just the shape of building things properly.
Where the easy wins live
- 01Unique <title> per page. Most sites get this wrong on at least 30% of routes.
- 02Compress images. WebP and AVIF are well-supported now. Saving 500KB per page lifts Lighthouse and helps Core Web Vitals.
- 03Lazy-load below-the-fold images and iframes. Native loading="lazy" is supported almost everywhere; use it.
- 04Inline critical CSS. The first paint should not wait for an external stylesheet.
- 05Preload key fonts. Font swap-in is one of the most common CLS triggers.
What we tell clients
- 01If you're building a content-heavy site or a marketing site, SEO is not optional. Pick a framework and team that make it the default.
- 02If you're building a logged-in product where organic search isn't the channel, SEO matters less — but still build the marketing site on something that ranks.
- 03Run Lighthouse weekly during development. Treat regressions like build failures.
- 04Set up Search Console before launch, not after. The early data is more useful than the late data.
- 05Don't trust the SEO audit tool that just installed itself in your Shopify. Most of them are wrong about most things.
The systems we ship that rank well share three things: server-rendered HTML, fast loading, and meta tags that were thought about before the launch. None of those are technically difficult. All of them require treating SEO as a feature, not a phase three.