Back to Blog

Next.js SEO best practices: server-side rendering and meta tags

SEO
Performance
Next.js
TypeScript
SSR

Optimizing your Next.js SaaS application for search engines requires server-side metadata generation, dynamic meta tags, canonical URLs, and sitemap configuration. From generateMetadata functions to locale-aware SEO utilities and Open Graph optimization, creating a comprehensive SEO system requires weeks of careful development. Fastack comes with a complete SEO package that handles metadata generation, locale-aware SEO, and sitemap generation—saving you weeks of development time.

Why SEO matters for SaaS

Proper SEO implementation is essential for SaaS applications:

  • Improved search engine rankings
  • Better social media sharing with Open Graph
  • Multi-language SEO with hreflang tags
  • Server-side rendering for better crawlability
  • Structured metadata for rich search results

What you get with Fastack

Fastack includes a complete SEO system with locale-aware metadata generation:

Server-side metadata generation

Fastack uses Next.js generateMetadata for server-side metadata generation:

apps/fastack-boilerplate/src/app/[locale]/layout.tsx
import { generateLocaleMetadata, getCanonicalUrl } from '@saas/i18n';
import { localeMetadata, routing } from '@/i18n/routing';
import type { Metadata } from 'next';

export async function generateMetadata({
  params,
}: {
  params: Promise<{ locale: string }>;
}): Promise<Metadata> {
  const { locale: localeParam } = await params;
  const locale = routing.locales.includes(localeParam as any)
    ? localeParam
    : routing.defaultLocale;
  const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'https://example.com';
  const pathname = '/';

  return generateLocaleMetadata(
    pathname,
    baseUrl,
    locale,
    routing,
    localeMetadata,
    {
      title: 'Fastack Boilerplate - Modern SaaS Starter Template',
      description: 'A production-ready SaaS boilerplate built with Next.js, TypeScript, and modern best practices. Get started building your SaaS faster.',
      keywords: ['SaaS', 'boilerplate', 'Next.js', 'TypeScript', 'starter', 'template', 'fastack', 'React'],
      authors: [{ name: 'Fastack Boilerplate' }],
      openGraph: {
        title: 'Fastack Boilerplate - Modern SaaS Starter Template',
        description: 'A production-ready SaaS boilerplate built with Next.js, TypeScript, and modern best practices.',
        type: 'website',
        siteName: 'Fastack Boilerplate',
      },
      twitter: {
        card: 'summary_large_image',
        title: 'Fastack Boilerplate - Modern SaaS Starter Template',
        description: 'A production-ready SaaS boilerplate built with Next.js, TypeScript, and modern best practices.',
      },
      alternates: {
        canonical: getCanonicalUrl(pathname, baseUrl, routing, locale),
      },
      manifest: '/manifest.json',
      other: {
        'mobile-web-app-capable': 'yes',
        'apple-mobile-web-app-capable': 'yes',
        'apple-mobile-web-app-status-bar-style': 'default',
      },
    }
  );
}

The generateMetadata function runs on the server for each page, generating dynamic metadata based on the current locale and page content. This ensures that search engines receive properly formatted metadata for each language version of your site.

Locale-aware SEO utilities

Fastack provides utilities for generating locale-aware SEO metadata:

packages/i18n/seo.ts
export function generateLocaleMetadata<Locale extends string>(
  pathname: string,
  baseUrl: string,
  locale: Locale,
  routing: RoutingConfig<Locale>,
  localeMetadata: Record<Locale, LocaleMetadata>,
  additionalMetadata?: Metadata
): Metadata {
  const validLocale = routing.locales.includes(locale)
    ? locale
    : routing.defaultLocale;
  const metadata = localeMetadata[validLocale];

  if (!metadata) {
    throw new Error(`Locale metadata not found for locale: ${locale}. Please ensure the locale is defined in localeMetadata.`);
  }

  const otherMetadata: Record<string, string> = {
    ...(additionalMetadata?.other as Record<string, string> | undefined),
    'og:locale': metadata.code,
    'og:locale:alternate': routing.locales
      .filter((l) => l !== validLocale)
      .map((l) => localeMetadata[l]?.code)
      .filter(Boolean)
      .join(', '),
  };

  return {
    ...additionalMetadata,
    alternates: {
      ...additionalMetadata?.alternates,
      languages: generateAlternateLanguages(pathname, baseUrl, routing),
    },
    other: otherMetadata,
  };
}

export function getCanonicalUrl<Locale extends string>(
  pathname: string,
  baseUrl: string,
  routing: RoutingConfig<Locale>,
  locale?: Locale
): string {
  const targetLocale = locale || routing.defaultLocale;

  if (targetLocale === routing.defaultLocale) {
    return `${baseUrl}${pathname}`;
  }

  return `${baseUrl}/${targetLocale}${pathname}`;
}

The generateLocaleMetadata function automatically generates hreflang tags, canonical URLs, and Open Graph locale metadata for all language versions of your site. The getCanonicalUrl function ensures that canonical URLs are properly formatted for each locale.

Sitemap generation

Fastack includes automatic sitemap generation for all locales:

apps/fastack-boilerplate/src/app/sitemap.ts
import { MetadataRoute } from 'next';
import { routing } from '@/i18n/routing';

export default function sitemap(): MetadataRoute.Sitemap {
  const baseUrl = process.env.NEXT_PUBLIC_APP_URL || 'https://example.com';

  const routes = [
    '',
    '/pricing',
    '/privacy-policy',
    '/terms-of-service',
    '/contact',
    '/cookie-policy',
    '/auth'
  ];

  const sitemapEntries: MetadataRoute.Sitemap = [];

  routing.locales.forEach((locale) => {
    routes.forEach((route) => {
      const url = locale === routing.defaultLocale
        ? `${baseUrl}${route}`
        : `${baseUrl}/${locale}${route}`;

      sitemapEntries.push({
        url,
        lastModified: new Date(),
        changeFrequency: route === '' ? 'weekly' : 'monthly',
        priority: route === '' ? 1 : 0.7,
      });
    });
  });

  return sitemapEntries;
}

The sitemap automatically generates entries for all routes in all locales, helping search engines discover and index all language versions of your site. Each entry includes proper priority and change frequency settings.

Time saved: 15+ hours

Implementing production-ready SEO from scratch typically requires:

  • Setting up generateMetadata functions (2-3 hours)
  • Creating locale-aware SEO utilities (3-4 hours)
  • Implementing canonical URLs (1-2 hours)
  • Generating hreflang tags (2-3 hours)
  • Creating sitemap generation (2-3 hours)
  • Configuring Open Graph tags (1-2 hours)
  • Testing SEO implementation (2-3 hours)

Total: 13-20 hours of development time that you save with Fastack.

Best practices included

Fastack follows SEO best practices:

  • Server-side metadata - Generated on the server for better SEO
  • Canonical URLs - Prevents duplicate content issues
  • Hreflang tags - Proper multi-language SEO
  • Open Graph - Optimized social media sharing
  • Sitemap generation - Automatic sitemap for all locales

Conclusion

SEO is essential for SaaS applications, and proper implementation requires careful attention to metadata, canonical URLs, and multi-language support. Fastack provides a complete SEO system that saves you weeks of development time while ensuring your site is properly optimized for search engines.

With Fastack, you get:

  • Server-side metadata generation with generateMetadata
  • Locale-aware SEO utilities for multi-language sites
  • Automatic canonical URL generation
  • Hreflang tag generation for all locales
  • Automatic sitemap generation
  • Open Graph and Twitter Card optimization
  • Production-ready SEO system built-in from day one

Ready to build your SaaS faster?

Get our scalable, production-ready boilerplate to save endless hours of development and setup

Next.js SEO best practices: server-side rendering and meta tags - Fastack