DEV Community

Cover image for Building an SEO-Optimized Blog with Next.js and MDX: From Routing to Rendering
Pavel Buyeu
Pavel Buyeu

Posted on

Building an SEO-Optimized Blog with Next.js and MDX: From Routing to Rendering

I’m an SEO & SEM expert with 18+ years of experience helping tech companies grow through search. I focus on developer-centric content, technical SEO, and demand generation for SaaS and B2B products. Currently, I lead SEO at Pynest — a software development company building solutions for fintech, healthtech, and edtech startups.

1. Why SEO Still Matters for Dev Blogs in 2025

If you’re setting up a technical blog in 2025, chances are someone’s told you, “Just focus on writing good content — Google will figure it out.” Sounds reassuring, but it doesn’t really hold up — especially when you're publishing dev-focused content in a space where competition is fierce, topics are highly specific, and discoverability can make or break your reach.

Search Engine Optimization (SEO) is still the most reliable long-term channel for attracting organic traffic to your dev blog — and more importantly, relevant traffic. Unlike social posts that fade in 48 hours or paid ads that vanish when the budget dries up, SEO compounds. A well-optimized technical article can rank for years, bringing in exactly the kind of audience you're trying to reach — developers, product managers, founders, or contributors.

In the world of developer tools, open-source projects, and technical startups, your blog isn’t just content — it’s a strategic asset. It fuels trust, drives sign-ups, supports documentation, and even improves hiring. That’s why overlooking technical SEO is a missed opportunity.

“Tech blogs often assume that because the content is good, it will perform. But Google needs help understanding structure, context, and authority — and that’s where SEO comes in.”
— Dominique Jackson, B2B SaaS content strategist

Why SEO matters specifically for dev blogs:
Your audience is search-oriented — developers often Google before they ask.

You’re likely using JavaScript-heavy frameworks that require intentional rendering setup.

Your content tends to be long-tail and technical, perfect for search — if structured well.

In this guide, we’ll walk through how to build an SEO-optimized blog with Next.js and MDX, making sure your great content doesn’t get buried under sites that simply render better.

2. Project Setup: Next.js, MDX, and File-Based Routing

For a modern dev blog, Next.js + MDX is a powerful combo: fast, flexible, and friendly to both developers and search engines — if configured right.

Why Next.js?
Next.js provides out-of-the-box support for:

  • Server-side rendering (SSR)
  • Static site generation (SSG)
  • Incremental Static Regeneration (ISR)

All three are critical for SEO because they ensure your content is crawlable and rendered at the right time. Googlebot still struggles with poorly hydrated JavaScript — and Next.js helps solve that with predictable rendering behavior.

Why MDX?

MDX lets you write content in Markdown while embedding React components directly in your posts. This is a huge win for dev blogs: you can include live code examples, interactive widgets, and custom formatting — without leaving the Markdown comfort zone.

You can also extend MDX frontmatter to include title, slug, description, date, tags, author, and SEO metadata — making it easier to automate head tags and structured data later on.

---
title: "How to Write a Custom ESLint Rule"
slug: "custom-eslint-rule"
description: "A step-by-step guide to building your own ESLint rule for team-wide code consistency."
date: "2025-05-20"
tags: ["eslint", "linters", "javascript"]
author: "pavel-buyeu"
---
Enter fullscreen mode Exit fullscreen mode

Recommended Folder Structure

To keep your content clean and scalable:

/pages
  /blog
    [slug].tsx
/posts
  my-post.mdx
  another-post.mdx
/layouts
  PostLayout.tsx
/lib
  mdx.ts
  getAllPosts.ts
Enter fullscreen mode Exit fullscreen mode

MDX files live in /posts/
Blog routes are handled via dynamic routing in /pages/blog/[slug].tsx

Content is loaded and parsed with gray-matter, next-mdx-remote, or contentlayer

This gives you full control over how posts are rendered, allows for custom components (like callouts or code blocks), and supports both SSR and static generation.

3. URL Structure and Slugs: Clean, Readable, and Consistent

Clean URLs aren’t just about aesthetics — they’re about trust, clarity, and SEO. A good blog URL should tell both humans and search engines exactly what to expect, without extra clutter or ambiguity.

What a good URL looks like:

/blog/custom-eslint-rule
Enter fullscreen mode Exit fullscreen mode

What to avoid:

/blog/post?id=12345  
/blog/2025/05/custom-eslint-rule/index.html
Enter fullscreen mode Exit fullscreen mode

Even though modern crawlers can parse complex URLs, clean and readable slugs tend to:

  • Get higher click-through rates in search results
  • Earn more backlinks (they look more trustworthy)
  • Improve long-term maintainability of your blog structure

Slugs from Frontmatter

If you’re using MDX, you should define slugs directly in frontmatter:

---
title: "Improving Core Web Vitals with Next.js"
slug: "core-web-vitals-nextjs"
---
Enter fullscreen mode Exit fullscreen mode

Then in your [slug].tsx page, you can fetch the appropriate MDX file by matching the slug from getStaticPaths.

Generate slugs automatically (optional)

If you don’t want to write slugs manually, you can generate them from the title using libraries like slugify:

import slugify from 'slugify';
const slug = slugify(title, { lower: true });
Enter fullscreen mode Exit fullscreen mode

But be careful — if your titles change, so will the URLs. Either store slugs separately or implement 301 redirects to avoid broken links and SEO penalties.

URL Nesting: Flat or Hierarchical?

For most blogs, a flat structure like /blog/my-post is ideal. If you’re building a larger knowledge base or documentation-style site, you might go deeper (e.g., /guides/seo/schema-markup), but simplicity helps with indexing and crawl budgets.

Clean, consistent URLs are one of the easiest SEO wins — and they pay off long-term. Don’t overthink it, but don’t ignore it either.

4. Meta Tags and Open Graph: Automating the Basics

Meta tags are still the backbone of how your pages appear in Google and social media previews. Even in 2025, failing to set them means leaving CTR, visibility, and shareability on the table.

If you want your blog post to:

  • show a clear title and description in the search,
  • render a nice preview card on Twitter or LinkedIn,
  • support accessibility and indexing, ...you need to get your metadata right — and make it easy to manage at scale.

What meta tags matter for dev blogs?

meta title — Appears in browser tabs and Google search
meta description — Shown in search snippets
meta property="og:title", og:description, og:image — For social previews
meta name="twitter:card", twitter:image, etc. — For Twitter-specific previews
link rel="canonical" — To prevent duplicate content issues

Automate it with a dynamic SEO component

You can create a simple SEO.tsx React component that pulls metadata from your MDX frontmatter:

components/SEO.tsx
import Head from 'next/head';
export const SEO = ({ title, description, image, slug }) => {
  const url = `https://yourdomain.com/blog/${slug}`;

  return (
    <Head>
      <title>{title}</title>
      <meta name="description" content={description} />
      <meta property="og:title" content={title} />
      <meta property="og:description" content={description} />
      <meta property="og:image" content={image} />
      <meta property="og:url" content={url} />
      <meta name="twitter:card" content="summary_large_image" />
      <link rel="canonical" href={url} />
    </Head>
  );
};
Enter fullscreen mode Exit fullscreen mode

Then in your blog post layout:

<SEO
  title={frontMatter.title}
  description={frontMatter.description}
  image={frontMatter.image}
  slug={frontMatter.slug}
/>
Enter fullscreen mode Exit fullscreen mode

This ensures every post has correct, structured metadata — without repeating yourself.

Bonus: Use next-seo if you want more control

The next-seo package offers a declarative way to manage SEO tags, including JSON-LD structured data and breadcrumbs. It's powerful, but your own component may be simpler and easier to customize for MDX-based blogs.

Proper meta tags aren't glamorous, but they’re what make your content findable and shareable. Automate them early, and your future self (and Google) will thank you.

5. Sitemap, Robots.txt and Canonicals

You can have the best content and meta tags in the world, but if search engines can’t crawl and index your pages properly — they won’t rank. That’s why every SEO-optimized dev blog needs a clean sitemap, a smart robots.txt, and well-configured canonical URLs.

These elements don’t just improve indexing — they tell crawlers what matters, what should be ignored, and how to treat duplicated or syndicated content.

Sitemap.xml: Show Google What You've Got

Your sitemap lists all the important pages on your site. This helps search engines crawl new or updated content faster, especially if you publish often.

The easiest way to generate one in a Next.js blog is by using next-sitemap:

npm install next-sitemap
Enter fullscreen mode Exit fullscreen mode

Then create a next-sitemap.config.js:

module.exports = {
  siteUrl: 'https://yourdomain.com',
  generateRobotsTxt: true,
  changefreq: 'weekly',
  sitemapSize: 5000,
  exclude: ['/drafts/*']
};
Enter fullscreen mode Exit fullscreen mode

And update package.json:

"scripts": {
  "postbuild": "next-sitemap"
}

Enter fullscreen mode Exit fullscreen mode

After building, you’ll get:
/sitemap.xml
/robots.txt

You can submit your sitemap manually via Google Search Console, or just let bots find it by referencing it in robots.txt.

Robots.txt: Give Crawlers Clear Instructions

Use robots.txt to allow or disallow paths — for example, blocking /admin or /api. If you're generating it via next-sitemap, it'll automatically include your sitemap reference.
Example:

User-agent: *
Allow: /
Disallow: /drafts/
Sitemap: https://yourdomain.com/sitemap.xml
Enter fullscreen mode Exit fullscreen mode

Be careful: a wrong Disallow rule can accidentally de-index your entire site. Always test with Google Search Console’s URL Inspection Tool.

Canonical URLs: Avoid Duplicate Content Issues

If you publish the same content across multiple platforms (your blog, Medium, Dev.to), canonical tags tell search engines which version is the "master copy." This helps you avoid splitting ranking signals across URLs.

Inside your SEO.tsx component, set:

<link rel="canonical" href={`https://yourdomain.com/blog/${slug}`} />
Enter fullscreen mode Exit fullscreen mode

If you're syndicating a post on Medium, add this to the Medium post’s header via the Import tool — Medium will respect the canonical link.

Clean sitemap. Smart robots.txt. Proper canonical URLs. These aren't "advanced SEO hacks" — they're foundations that make everything else work.

6. Structured Data: Schema.org for BlogPosts and Authors

Structured data helps search engines understand your content — not just crawl it. By using Schema.org markup, you can give Google explicit signals about what a page is, who wrote it, when it was published, and what it's about.

For a developer blog, this unlocks:

  • Rich snippets (e.g. author, date, featured image in search results)
  • Eligibility for Google Discover
  • Better clarity for voice search and AI-powered results

And it’s easy to add using JSON-LD in Next.js.

Schema Types You’ll Need

At a minimum, a blog should include:

  1. BlogPosting — For individual posts
  2. Person — For authors
  3. Organization — If publishing under a company or brand

Example JSON-LD for a Blog Post

Here’s a simple StructuredData.tsx component:

// components/StructuredData.tsx
import Head from 'next/head';

export const StructuredData = ({ title, description, date, author, slug }) => {
  const jsonLd = {
    "@context": "https://schema.org",
    "@type": "BlogPosting",
    "headline": title,
    "description": description,
    "datePublished": date,
    "author": {
      "@type": "Person",
      "name": author
    },
    "mainEntityOfPage": {
      "@type": "WebPage",
      "@id": `https://yourdomain.com/blog/${slug}`
    },
    "publisher": {
      "@type": "Organization",
      "name": "Your Company Name",
      "logo": {
        "@type": "ImageObject",
        "url": "https://yourdomain.com/logo.png"
      }
    }
  };

  return (
    <Head>
      <script type="application/ld+json">
        {JSON.stringify(jsonLd)}
      </script>
    </Head>
  );
};
Enter fullscreen mode Exit fullscreen mode

Include it in your blog post layout alongside .

Validate Your Schema

Use these tools to check your structured data:

  • Google Rich Results Test
  • Schema Markup Validator

Validation helps catch common issues: missing fields, incorrect types, or malformed JSON.

Structured data is invisible to users but powerful for machines. In a world of AI-driven search and zero-click answers, speaking Google’s language gives your blog a real edge.

7. Performance, SSR, and Incremental Static Regeneration

Search engines (and readers) love fast pages. Google’s Core Web Vitals are now baked directly into ranking signals — especially on mobile — and for dev blogs, load speed can be the difference between engagement and bounce.
Luckily, Next.js gives you several rendering strategies to balance speed, freshness, and SEO.

Why Performance Matters for SEO

  • LCP (Largest Contentful Paint) affects how fast users feel the page loads
  • FID (First Input Delay) reflects interactivity
  • CLS (Cumulative Layout Shift) tracks visual stability

All of these influence how Google ranks your page — especially if you’re fighting for visibility in a competitive tech niche.

Rendering Strategies: SSR, SSG, ISR

Let’s break down how Next.js helps:

  • SSG (Static Site Generation)
  • Content is built at deploy time
  • Fastest for users (HTML is prebuilt)

Ideal for blog posts that don’t change often

export async function getStaticProps() { ... }
Enter fullscreen mode Exit fullscreen mode

SSR (Server-Side Rendering)

  • HTML is rendered on each request
  • Slower but supports real-time content
  • Use only when dynamic data must be fresh
export async function getServerSideProps() { ... }
Enter fullscreen mode Exit fullscreen mode

ISR (Incremental Static Regeneration)

  • Static generation with scheduled revalidation
  • Perfect for blogs: fast + updatable
export async function getStaticProps() {
  return {
    props: { ... },
    revalidate: 60 // seconds
  };
}
Enter fullscreen mode Exit fullscreen mode

Tip: Most tech blogs don’t need SSR. Stick to SSG or ISR for best performance + SEO balance.

How to Improve Core Web Vitals

  • Compress and lazy-load images (next/image does this well)
  • Avoid a layout shift by always setting the width/height on images
  • Limit custom fonts or self-host them
  • Use next/script with strategy="lazyOnload" for third-party tools
  • Minimize hydration in static content — don’t overuse interactive components

Test Your Performance
Use Lighthouse (in Chrome DevTools or PageSpeed Insights) to check:

  • LCP < 2.5s
  • CLS < 0.1
  • FID (now INP) < 200ms

Also, test on real mobile devices — Google does.

Next.js gives you full control over how your content is built and served. Choose the right strategy for your blog type, and your site will feel snappy and stay crawlable.

8. Deploying and Monitoring SEO Health

Getting your blog live is just the beginning. The real work is in keeping it fast, crawlable, and indexed — consistently. That’s why deployment and SEO monitoring should be part of your ongoing workflow, not something you check once a quarter.

Where to Deploy Your Blog

For most dev blogs built with Next.js, these three options are the most common:

  • Vercel – Native support for Next.js, built-in image optimization, fast CDN, automatic ISR support, Git-based deployments.
  • Netlify – Great for JAMstack, supports Next.js with adapters. Also has built-in forms, split testing, and serverless functions.
  • Custom VPS or containerized deployment (e.g., Docker + Nginx) – Maximum control, but you’ll need to handle caching, CDN, and ISR logic manually.

Unless you have specific infrastructure needs, Vercel is often the easiest and fastest path — especially if you're using ISR.

Connect to Google Search Console Immediately

Once deployed:

  • Submit your sitemap.xml
  • Verify your domain (DNS or file upload)
  • Monitor index coverage, mobile usability, and performance reports

Use the URL Inspection Tool to check how Googlebot sees each blog post. It helps catch issues like:

  • Render-blocking scripts
  • Canonical mismatches
  • Missing meta tags

Set Up Regular SEO Monitoring

  1. Ahrefs / Semrush / SE Ranking – Track keyword rankings, backlinks, and crawl health over time.
  2. Google Search Console – Monitor impressions, clicks, CTR, and errors directly from the source.
  3. Simple tools like Screaming Frog or Sitebulb – Periodic crawls help catch broken links, missing titles, duplicate content.
  4. 404 and redirect tracking – Set up basic monitoring for dead URLs and log them. A broken blog link can tank your ranking on evergreen posts.
  5. Core Web Vitals tracking – Use tools like web.dev/measure and PageSpeed Insights regularly — or integrate Lighthouse CI.

Automate Where You Can

  • Set up weekly reports from Search Console
  • Create alerts for traffic drops or crawl issues
  • Add Slack/Email notifications via Zapier or your analytics tool

Deploying is just step one. Long-term SEO health comes from treating your blog like a living system — monitored, maintained, and improved over time.

10. Conclusion: SEO as Code — Not an Afterthought

A well-structured dev blog isn’t just a place to publish technical thoughts — it’s a discoverability engine. But too many developer teams treat SEO as a checklist, or worse, an afterthought once the content is live.

What we’ve covered here — routing, metadata, performance, schema, monitoring — isn’t “just for marketing.” It’s engineering. It’s a system design for visibility.

In 2025, Google expects your blog to:

  • Load fast on mobile
  • Be crawlable and semantically clear
  • Have a structure it can trust and understand
  • Provide real value to a specific audience

And all of that starts in code.

When you treat SEO as part of the build process — not just something slapped on after publishing — you build faster, rank higher, and maintain quality at scale.

If you can ship a clean API, you can ship a clean page. And Google will thank you for it.

Resources:
Official Next.js SEO Docs

Schema.org BlogPosting reference

Lighthouse CI

next-sitemap

next-seo

Top comments (0)