DEV Community

seller-mind
seller-mind

Posted on

How I Built a Next.js SaaS Starter Kit with Edge SEO Tools

When I first started building SaaS products, I noticed a frustrating pattern. Every time I had a new idea, I would spend the first three to four days just wiring up the same foundational code. I’d configure NextAuth, set up Stripe checkout sessions, and build the webhook handlers. By the time I actually started writing code for my unique product logic, I was already burnt out. On top of that, whenever I wanted to include a simple SEO analysis tool for my users, I’d hit a wall. I didn't want to pay for expensive third-party APIs just to parse a few meta tags, but running heavy DOM parsing on a standard serverless function felt slow and resource-intensive. So I decided to build something.

The cost of ignoring boilerplate efficiency is massive, especially for indie developers. If you lose three days to setup on every project, that’s weeks of lost development time over a year. But the bigger issue is the architecture trade-offs we make when we rush. When you need an SEO checker, you usually have two choices: use a heavy Node.js library on your main server (which increases cold starts and memory usage) or pay for an external API. Neither is ideal for a lightweight SaaS. Furthermore, if your server is hosted in a single region, users from across the globe experience high latency when running these checks. I needed a way to standardize the boring stuff while keeping the edge computing fast and cheap.

I created SaaSLaunch, a production-ready SaaS boilerplate using Next.js 14+ with the App Router, Stripe billing, and NextAuth.js. But the core architectural decision was integrating Cloudflare Workers for edge-side API routes.

For authentication, leveraging NextAuth.js with the App Router requires a slightly different setup than the old Pages router. We define the auth options in a dedicated configuration file and use the auth wrapper in our middleware to protect the dashboard routes. This keeps the session management secure and centralized.

Let’s look at the Stripe integration first. Using the Next.js App Router, we can create clean, type-safe API routes. Here is how the checkout session is structured:

// Next.js API route for Stripe checkout (App Router)
import { NextResponse } from 'next/server';
import Stripe from 'stripe';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);

export async function POST(req: Request) {
  const { priceId, userId } = await req.json();

  const session = await stripe.checkout.sessions.create({
    mode: 'subscription',
    payment_method_types: ['card'],
    line_items: [{ price: priceId, quantity: 1 }],
    success_url: `${process.env.APP_URL}/dashboard?success=true`,
    cancel_url: `${process.env.APP_URL}/pricing?cancelled=true`,
    client_reference_id: userId,
  });

  return NextResponse.json({ url: session.url });
}
Enter fullscreen mode Exit fullscreen mode

Handling Stripe webhooks was another area where this setup saved time. Verifying the webhook signatures and updating the database based on the checkout.session.completed event is fully typed, which gave me peace of mind when processing real payments.

But for the SEO analysis tool, I wanted to push the compute to the edge. By using Cloudflare Workers, the SEO checker runs in data centers all over the world, drastically reducing latency for global users.

Here is the Cloudflare Worker code that handles the edge SEO analysis:

// Cloudflare Worker for edge SEO analysis
export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    if (url.pathname !== '/api/analyze') {
      return new Response('Not found', { status: 404 });
    }

    const targetUrl = url.searchParams.get('url');
    if (!targetUrl) {
      return new Response(JSON.stringify({ error: 'Missing url' }), {
        status: 400,
        headers: { 'Content-Type': 'application/json' },
      });
    }

    // Fetch target page at the edge (low latency worldwide)
    const response = await fetch(targetUrl, {
      cf: { cacheTtl: 300, cacheEverything: true },
    });
    const html = await response.text();

    // Run SEO checks (regex-based, no DOM needed)
    const title = html.match(/<title[^>]*>([^<]*)<\/title>/i)?.[1] || '';
    const desc = html.match(/<meta[^>]*name=["']description["'][^>]*content=["']([^"']*)["']/i)?.[1] || '';
    const h1Count = (html.match(/<h1[ >]/gi) || []).length;

    return new Response(JSON.stringify({ title, desc, h1Count }), {
      headers: { 'Content-Type': 'application/json' },
    });
  },
};
Enter fullscreen mode Exit fullscreen mode

The trade-off here is that we can't use heavy DOM parsers in this specific lightweight edge environment without increasing the bundle size significantly. Instead, we use regex-based parsing. For basic SEO checks like extracting the title, meta description, and counting H1 tags, regex is incredibly fast and keeps the worker execution time in the single-digit milliseconds.

Building this architecture taught me a lot about the balance between developer experience and runtime performance. What worked exceptionally well was the one-click deployment to both Vercel for the Next.js frontend and Cloudflare Pages for the edge workers. It completely removed the deployment friction. The TypeScript-first approach also paid off; having full type safety across the Stripe webhooks and NextAuth callbacks prevented so many runtime errors before they ever reached production.

What surprised me the most was the performance difference in the SEO tool. Running the regex-based edge worker was noticeably faster than the traditional serverless functions I used in my previous projects, especially for users outside the US East coast. If I were to change one thing, I would probably add a few more OAuth providers out of the box, though NextAuth makes it relatively painless to add them manually now.

If you want to see how this edge SEO analysis works in practice without setting up the boilerplate yourself, I’ve made a live version available. You can test how the edge worker analyzes your site's basic SEO metrics right now.

Try the free SEO Checker here: https://saaslaunch.dev/free-tools/seo-checker


Full disclosure: I'm the developer of SaaSLaunch. I built this because I needed it myself.

Top comments (0)