SEO as Product Infrastructure, Not an Afterthought
Treating SEO as engineering infrastructure rather than a marketing checklist. Rendering, metadata, structured data, and the crawl as a system.
SEO has a reputation problem among engineers. It sounds like a marketing concern, a checklist of keywords and meta tags handed over after the real work is done. That framing is why so many otherwise excellent products are invisible in search. Good SEO is infrastructure, and the parts that matter most are engineering decisions about rendering, structure, and how a crawler experiences your site.
The crawler is a user with constraints
The mental shift that makes SEO click is to treat the crawler as a real user, one with specific limitations. It arrives without your application state, follows links, has a budget for how much it will fetch, and forms an understanding of each page from what is actually in the response. Every decision about how your pages are rendered and linked is a decision about what that user can perceive.
If a crawler cannot reach a page through a real link, cannot render its content without executing a pile of client JavaScript, and cannot tell what the page is about from its markup, then for search purposes the page does not exist.
Rendering is the first SEO decision
The single most consequential SEO choice is how content reaches the page. Content that is server rendered is in the HTML response, immediately available to any crawler. Content that is fetched on the client after hydration may or may not be seen, depending on the crawler's rendering budget and behavior. For anything you want indexed, the content needs to be in the server response.
This is why frameworks that default to server rendering have a structural SEO advantage. Your primary content, headings, and links should exist in the initial HTML, not appear after a client side fetch resolves.
The failure mode here is subtle because it is invisible during normal development. On your fast laptop, the client fetch resolves in milliseconds and the content appears, so the page looks perfectly indexable to you. The crawler experiences something different. It may render JavaScript on a deferred queue, with a budget that runs out, and it may index the first pass of HTML long before your client fetch ever fires. The result is a page that looks complete to every human who visits and looks empty to the system deciding whether to rank it. The way to catch this is to view the raw HTML response, the actual bytes the server sent, with JavaScript disabled or through a fetch rather than a browser. If your headline, body, and links are not in that response, they are not reliably part of what search sees, no matter how good the page looks once hydrated.
export async function generateMetadata({ params }): Promise<Metadata> {
const post = await getPost(params.slug);
return {
title: post.title,
description: post.excerpt,
alternates: { canonical: `/blog/${post.slug}` },
openGraph: { title: post.title, description: post.excerpt },
};
}
Generating metadata on the server, per page, means every route ships correct, specific tags in its initial response rather than a generic default that some client script patches later.
Canonicals and the duplicate content trap
A large share of real SEO problems are self inflicted duplicate content. The same page reachable at multiple URLs, with and without a trailing slash, with tracking parameters, on both the apex and www subdomain, splits ranking signals across copies. The fix is twofold: redirect aggressively to one canonical host and path shape, and set an explicit canonical URL on every page.
A permanent redirect from the www subdomain to the apex, or vice versa, is not a cosmetic preference. It consolidates signals onto one origin so the crawler does not treat your site as two competing copies.
The tracking parameter case deserves specific attention because it is where well meaning marketing work quietly damages SEO. A campaign appends parameters to share links, and now the same article is reachable at a dozen URLs that differ only in their query string. Without a canonical, each of those is a candidate for indexing, and the ranking signal that should accrue to one strong page is smeared across a dozen weak ones. The canonical tag is the fix: every variant declares the clean URL as its canonical, and the crawler folds the signals back together. The discipline that makes this reliable is deriving the canonical from the route itself, in shared infrastructure, rather than asking each page author to remember it. A canonical that a human has to set by hand is a canonical that will be wrong on the pages that matter most.
Structured data is how you speak the crawler's language
Structured data, expressed as JSON-LD, tells search engines what a page is in a vocabulary they understand. An article, a product, a person, a set of FAQs. It does not change what users see, but it changes how your page can be presented in results, and it removes ambiguity about the page's meaning.
const articleLd = {
"@context": "https://schema.org",
"@type": "BlogPosting",
headline: post.title,
description: post.excerpt,
datePublished: post.date,
author: { "@type": "Person", name: author.name },
};
The discipline here is to only describe what is genuinely on the page. Structured data that claims things the page does not show is a liability, not an advantage, and search engines are good at detecting the mismatch.
The link graph is your site's skeleton
Crawlers discover pages by following links, so your internal linking is the skeleton of your discoverability. Pages that are only reachable through a client side router action, a button that pushes to a route without a real anchor, may never be found. Use real anchor elements with real hrefs for anything that should be crawlable, and make sure important pages are reachable within a few links of the home page.
A sitemap helps a crawler find pages efficiently, but it is a supplement to good internal linking, not a substitute. A page in the sitemap that nothing links to sends a confusing signal: you listed it, but your own site does not consider it important enough to reference.
Performance is an SEO input
Core Web Vitals are ranking inputs, which means the performance work you do for users is also SEO work. A fast, stable page is rewarded twice, once by users who stay and once by the ranking that performance feeds. This is the satisfying part of treating SEO as infrastructure: the same engineering that makes a site good to use makes it discoverable.
The link between performance and ranking is worth making concrete because it changes how you prioritize. A page that scores poorly on Largest Contentful Paint or shifts under the user as it loads is not just losing the users who bounce, it is also handing a ranking signal to a competitor whose page is stable and fast. This means the streaming work, the image optimization, and the layout stability work that a performance engineer does are not a separate track from SEO, they are SEO. When you frame it this way, the perennial argument about whether to invest in performance resolves itself, because the investment pays in two currencies at once. The teams that treat Core Web Vitals as a user experience concern and the teams that treat them as an SEO concern are funding the same work, and they should stop pretending it is two budgets.
Practical takeaways
- Treat the crawler as a real user with constraints: no application state, a finite fetch budget, and an understanding of each page built from the actual response bytes.
- Verify your primary content, headings, and links exist in the raw server HTML, not just after client hydration, by inspecting the response with JavaScript disabled.
- Generate metadata per route on the server so every page ships specific, correct tags rather than a generic default patched later.
- Redirect aggressively to one canonical host and path shape, and set an explicit canonical URL, derived from the route in shared code, on every page to defeat duplicate content.
- Emit JSON-LD that describes only what is genuinely on the page, because a mismatch between structured data and visible content is a liability.
- Use real anchors with real hrefs for anything crawlable, keep important pages within a few links of the home page, and treat a sitemap as a supplement to internal linking, not a substitute.
- Fund Core Web Vitals work once and count it twice, as both user experience and an SEO ranking input.
Building it into the system
The way to make SEO durable is to bake it into shared infrastructure rather than relying on individuals to remember it per page. A metadata helper that every route uses. A JSON-LD component that pages compose. A canonical URL derived automatically from the route. A redirect rule that enforces one host. When these are part of the framework your team builds on, correct SEO becomes the default outcome of shipping a page rather than a separate task that competes for attention and loses.
That is the whole argument. SEO is not a marketing layer applied at the end. It is a set of engineering guarantees about how your pages render, link, and describe themselves, and the teams that treat it that way are the ones whose work gets found.