DEV Community

Mayuresh Smita Suresh
Mayuresh Smita Suresh Subscriber

Posted on

pSEO in NextJs and how it helped me to rank on google for so many keywords.

Programmatic SEO with Next.js: What Works & What Breaks

Spent 6 months building pSEO pages in Next.js. Here's what actually works (and what breaks):

What is Programmatic SEO (pSEO)?

Programmatic SEO is automatically generating hundreds or thousands of SEO-optimized pages from a template and database. Instead of manually writing each page, you create one template and populate it with data.

Classic Examples:

  • Zillow: Millions of pages like "Homes for sale in [City], [State]"
  • Nomad List: "Best cities for [job type]"
  • TripAdvisor: "[Activity] in [Location]"
  • MoneySense AI: "[this] vs [that] financial term explained"

You can checkout MoneySense AI - Learn Page

Each page targets a specific long-tail keyword, has unique content, and ranks independently in search results.


Why Next.js is Perfect for pSEO

1. Static Site Generation (SSG) with Dynamic Routes

Next.js pre-renders every page as static HTML. Google sees fully-rendered content instantly - no client-side rendering issues.

// Generate 10,000 pages at build time
export async function generateStaticParams() {
  const calculations = await db.getAllCalculatorTypes();
  return calculations.map(calc => ({ slug: calc.slug }));
}
Enter fullscreen mode Exit fullscreen mode

2. Incremental Static Regeneration (ISR)

Game-changer alert! Generate 10,000+ pages at build time, update them on-demand. We're using this for MoneySense calculators - each financial tool gets its own optimized page.

You don't need to rebuild your entire site when data changes. ISR regenerates individual pages on-demand:

export const revalidate = 86400; // Update every 24 hours
Enter fullscreen mode Exit fullscreen mode

This is crucial for pSEO - you can have 50,000 pages without 2-hour build times.

3. Built-in SEO Optimization

App Router's metadata API makes SEO trivial. Dynamic meta tags, structured data, Open Graph - all type-safe and colocated with your page logic. No more fighting with react-helmet.

export const metadata = {
  title: "`${calculatorName} - Free Online Calculator`,"
  description: "`Calculate ${calculatorName}...`,"
  openGraph: {
    title: "`${calculatorName} Calculator`,"
    description: "`Free online ${calculatorName} calculator`,"
    images: ['/og-image.jpg'],
  }
}
Enter fullscreen mode Exit fullscreen mode

4. Server Components (App Router)

Fetch data directly in your component without client-side overhead. Zero JavaScript sent to client for static content. Faster page loads = better SEO rankings.

async function CalculatorPage({ params }) {
  const data = await getCalculatorData(params.slug);
  return <Calculator data={data} />;
}
Enter fullscreen mode Exit fullscreen mode

5. Edge Rendering

Edge functions let you personalize content by location without sacrificing SEO. Serve UK-specific financial content to UK users while keeping everything server-rendered.

export const runtime = 'edge';

export default function Page({ searchParams }) {
  const country = headers().get('x-vercel-ip-country') || 'US';
  const currency = country === 'GB' ? '£' : '$';

  return <Calculator currency={currency} />;
}
Enter fullscreen mode Exit fullscreen mode

UK user sees "£" and UK tax rates. US user sees "$" and US rates. Same URL, different content, all server-rendered.


The Pain Points

Build Times Explode Fast

50k pages = 45-minute builds even with caching.

Solution: Generate most popular pages statically, rest on-demand with ISR revalidation.

export async function generateStaticParams() {
  // Only generate top 1000 pages at build time
  const topPages = await db.getTopPages(1000);
  return topPages.map(page => ({ slug: page.slug }));
}

// Rest will be generated on-demand with ISR
export const dynamicParams = true;
export const revalidate = 86400;
Enter fullscreen mode Exit fullscreen mode

Database Costs Spike Hard

Every page generation hits your DB. We shifted to edge caching with Vercel KV to avoid destroying our Postgres bill.

import { kv } from '@vercel/kv';

async function getCalculatorData(slug) {
  const cached = await kv.get(`calc:${slug}`);
  if (cached) return cached;

  const data = await db.getCalculator(slug);
  await kv.set(`calc:${slug}`, data, { ex: 86400 });
  return data;
}
Enter fullscreen mode Exit fullscreen mode

Duplicate Content Risks Are Real

If you're auto-generating pages, you need robust canonicalization and noindex strategies. Google will penalize thin content.

export const metadata = {
  robots: {
    index: pageQualityScore > 7, // Only index high-quality pages
    follow: true,
  },
  alternates: {
    canonical: `https://example.com/${slug}`,
  }
}
Enter fullscreen mode Exit fullscreen mode

Architecture That Works

Here's our proven workflow:

  1. Seed your DB with target keywords
  2. Generate page templates with unique H1s/titles
  3. Use ISR with 24hr revalidation
  4. Monitor GSC for thin content flags
  5. Prune low-performing pages
// Example: Automated quality monitoring
async function prunePages() {
  const pages = await db.getAllPages();

  for (const page of pages) {
    const analytics = await getGSCData(page.url);

    if (analytics.impressions < 100 && analytics.clicks < 5) {
      // Mark as noindex after 90 days
      await db.updatePage(page.id, { noindex: true });
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Why Not Other Frameworks?

Framework Pros Cons
WordPress/PHP Easy to start Slow, database-heavy, doesn't scale to 10k+ pages efficiently
Pure React (CRA) Familiar Client-side rendering kills SEO. Google has to execute JavaScript to see content
Gatsby Good SSG Build times are brutal for large-scale pSEO. 50k pages = hours of building
Astro Fast, simple Good alternative, but Next.js has better data fetching patterns and middleware for personalization

Real Results

AllProCalculator Case Study

Our AllProCalculator project went from 0 to 12k monthly organic visits in 4 months using this approach.

Stack:

  • Template: "Calculate [X]" pages
  • Data: 200+ calculator types in PostgreSQL
  • Build: ISR with 24hr revalidation
  • Hosting: Vercel with edge caching

Key Metrics:

  • 200+ indexed pages
  • Average page load: 0.8s
  • Core Web Vitals: All green
  • 12,000 monthly organic visits

Is It Worth It?

Absolutely - if you have genuine unique content for each page.

Not worth it if you're just keyword stuffing templated pages.

Next.js 14's partial prerendering could solve the build time issue, but it's still experimental.

The combination of SSG performance + ISR flexibility + built-in SEO tools makes Next.js the best choice for programmatic SEO at scale.


Getting Started

Ready to build your own pSEO site? Here's a quick starter:

npx create-next-app@latest my-pseo-site
cd my-pseo-site
Enter fullscreen mode Exit fullscreen mode
// app/[slug]/page.js
export async function generateStaticParams() {
  const items = await db.getAllItems();
  return items.map(item => ({ slug: item.slug }));
}

export async function generateMetadata({ params }) {
  const item = await db.getItem(params.slug);

  return {
    title: `${item.title} - Your Site`,
    description: item.description,
  };
}

export default async function Page({ params }) {
  const item = await db.getItem(params.slug);
  return <Article data={item} />;
}

export const revalidate = 86400; // 24 hours
Enter fullscreen mode Exit fullscreen mode

Start small, validate your content quality, then scale up. Monitor Google Search Console religiously for thin content warnings.


Building pSEO at scale? I'd love to hear about your challenges. Drop a comment below!

Top comments (0)