Configuration & Best Practices

Configure SEO settings in Plainform and follow best practices for optimal search engine visibility

This page covers how to configure Plainform's SEO features and follow best practices.

Environment Variables

Plainform requires the site URL for sitemap generation and metadata:

.env
SITE_URL="https://yourdomain.com"
NEXT_PUBLIC_SITE_URL="https://yourdomain.com"
  • NEXT_PUBLIC_SITE_URL: Used by both next-sitemap for sitemap generation and metadata API for canonical URLs (accessible on both client and server)
  • SITE_URL: Server-side base URL for API routes and server actions. Keep it aligned with NEXT_PUBLIC_SITE_URL.

In development, use http://localhost:3000 for both variables.

Sitemap Configuration

The next-sitemap.config.js file controls sitemap generation:

next-sitemap.config.js
module.exports = {
  siteUrl: process.env.NEXT_PUBLIC_SITE_URL,
  generateRobotsTxt: true,
  exclude: [
    '/icon*.png',
    '/icon*.svg',
    '/apple-icon*',
    '/favicon.ico',
    '/opengraph-image*',
    '*.json',
    '/order',
    '/order*',
    '/sign-in',
    '/sign-in*',
    '/sign-up',
    '/sign-up*',
    '/forgot-password',
    '/forgot-password*',
    '/sso-callback',
    '/sso-callback*',
    '/legal/privacy-policy',
    '/legal/terms-and-conditions',
  ],
  additionalPaths: async () => {
    const defaultChangeFreq = 'daily';
    const defaultPriority = 0.7;
    const lastMod = new Date().toISOString();

    const additionalRoutes = [
      {
        loc: '/blog',
        changefreq: defaultChangeFreq,
        priority: defaultPriority,
        lastmod: lastMod,
      },
    ];

    return additionalRoutes;
  },
};

Generate sitemap:

Terminal
npm run build

This creates public/sitemap.xml and public/robots.txt.

Auth pages, the order confirmation page, callback routes, generated assets, and the included legal pages are excluded from the sitemap. Auth and order pages also set robots.index: false in their page metadata.

Robots.txt Configuration

Customize robots.txt in next-sitemap.config.js:

next-sitemap.config.js
module.exports = {
  siteUrl: process.env.NEXT_PUBLIC_SITE_URL,
  generateRobotsTxt: true,
  robotsTxtOptions: {
    policies: [
      { userAgent: '*', allow: '/' },
      { userAgent: '*', disallow: '/admin' },
      { userAgent: '*', disallow: '/api' },
    ],
  },
};

Metadata Best Practices

Page Titles

Example metadata
import { siteConfig } from '@/config/siteConfig';

export function generateMetadata() {
  return {
    title: `Page Title | ${siteConfig.siteName}`,
    // Or use template from root layout:
    title: 'Page Title', // Becomes "Page Title | MyApp"
  };
}

Best practices:

  • Keep titles under 60 characters
  • Include primary keyword
  • Make titles unique per page

Meta Descriptions

Example metadata
export function generateMetadata() {
  return {
    description: 'Learn how to configure SEO in Plainform with sitemaps, metadata, and performance optimization.',
  };
}

Best practices:

  • 150-160 characters optimal length
  • Include primary keyword naturally
  • Make descriptions unique per page

Open Graph Tags

Example metadata
export function generateMetadata() {
  return {
    openGraph: {
      title: 'Page Title',
      description: 'Page description',
      url: 'https://yourdomain.com/page',
      images: ['/og-image.jpg'],
      type: 'website',
    },
    twitter: {
      card: 'summary_large_image',
      title: 'Page Title',
      description: 'Page description',
      images: ['/og-image.jpg'],
    },
  };
}

Image requirements: 1200x630px, JPG or PNG, under 1MB.

Canonical URLs

Set canonical URLs with alternates.canonical. Plainform uses relative canonical paths because app/layout.tsx defines metadataBase from NEXT_PUBLIC_SITE_URL.

Example metadata
export const metadata = {
  title: 'Page Title',
  alternates: {
    canonical: '/page',
  },
};

For MDX-backed pages, use the generated page URL:

app/(base)/blog/[...slug]/page.tsx
return {
  title: page?.data?.title,
  description: page?.data?.summary,
  alternates: {
    canonical: page?.url,
  },
  openGraph: {
    url: env.NEXT_PUBLIC_SITE_URL + page?.url,
  },
};

Performance Best Practices

Image Optimization

Always use Next.js Image component:

Optimized images
import Image from 'next/image';

<Image
  src="/hero.jpg"
  alt="Hero image"
  width={1200}
  height={600}
  priority  // For above-the-fold images
/>

Font Optimization

app/layout.tsx
import { Inter } from 'next/font/google';

const inter = Inter({ subsets: ['latin'] });

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={inter.className}>
      <body>{children}</body>
    </html>
  );
}

Content Best Practices

Heading Hierarchy

Use proper heading structure:

Semantic HTML
<h1>Page Title</h1>
<h2>Section Title</h2>
<h3>Subsection Title</h3>

Rules: One h1 per page, don't skip heading levels.

Alt Text

Provide descriptive alt text:

Alt text
<Image
  src="/product.jpg"
  alt="Dashboard showing analytics"
  width={800}
  height={600}
/>

Monitoring SEO

Google Search Console

  1. Verify your site at search.google.com/search-console
  2. Submit sitemap: https://yourdomain.com/sitemap.xml
  3. Monitor indexing status and search performance

Lighthouse Audits

Run Lighthouse in Chrome DevTools or CLI:

Terminal
npx lighthouse https://yourdomain.com --view

Target 90+ scores for Performance, Accessibility, Best Practices, and SEO.

Next Steps

How is this guide ?

Last updated on

On this page