BOB Docs
FrontendTutorials

SEO

SEO Setup

Nowadays, SEO is very important. BOB has the most important SEO features built-in and ready to use. You can set up everything in seconds. Each layout uses the generateDefaultMetadata function to fill in metadata for every page. You can always override it, but by default, all data is taken from .env variables.

Meta Tags

Example .env setup:

# SEO
NEXT_HOST_URL=http://localhost:3000
NEXT_PUBLIC_TITLE=BOB fresh instance
NEXT_PUBLIC_DESCRIPTION=BOB default description
AUTHOR_NAME=alex_b27g
AUTHOR_URL=https://businessorientedprogramming.com
APPLICATION_NAME=BOB

These values will be used as default meta tags for every page. You can override them on any page (see Override Meta Tags).

Icons

There are also icons that appear in browser tabs and on Apple devices. You can replace these files with your custom icons:

  • /public/branding/favicon.ico
  • /public/branding/branding/favicon.ico
  • /public/branding/apple-touch-icon.png

Make sure the images have the correct dimensions to avoid display issues.

Social Media Open Graph (OG)

You can set default Open Graph (OG) and Twitter meta tags using environment variables:

# TWITTER / X
TWITTER_LOGIN=twitterLoginlike:@alex_b27g

This will set default metadata for social media previews across the whole app.

Open Graph / Twitter Images

By default, og:images and twitter images for link previews are here:

  • /public/branding/opengraph-image.jpg
  • /public/branding/twitter-image.jpg

💡 Recommended image settings for social media:

  • Minimum size: 1200px by 675px
  • File size: Max 5MB
  • Ratio: 1.91:1

You can easily generate OG images here: https://ogimagemaker.com/

Override Meta Tags

Each page or layout can override default meta tags. You can pass custom props to generateDefaultMetadata to set specific tags per page.

Example for a documentation page:

export async function generateMetadata(props: { params: Promise<{ slug?: string[] }> }) {
    const params = await props.params;
    const page = docs_source.getPage(params.slug);
 
    if (!page) {
        return notFound();
    }
 
    const description = page.data.description ? page.data.description.toString() : undefined;
 
    return generateDefaultMetadata({
        title: page.data.title.toString(),
        description: description
    });
}

robots.txt

You can easily modify robots.txt by editing the app/robots.tsx file:

export default function robots(): MetadataRoute.Robots {
    return {
        rules: {
            userAgent: '*',
            allow: '/',
            disallow: [
                '/dashboard*',
                '/invitations*',
                '/organization*',
                '/settings',
                '/subscriptions*'
            ]
        },
        sitemap: process.env.NEXT_PUBLIC_SITEMAP_URL || "http://localhost:3000",
    }
}

This will allow search engines to index public pages while blocking private ones.

Sitemap

A sitemap helps search engines find all your website pages. This is crucial for SEO, especially if you have a blog or documentation.

Example of sitemap generation:

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
    const host = process.env.NEXT_HOST_URL || 'http://localhost:3000';
 
    const data: MetadataRoute.Sitemap = [
        {
            url: host,
            lastModified: new Date().toISOString(),
            changeFrequency: 'yearly',
            priority: 1,
        },
        // Add other important static pages like About, Contact, etc.
    ];
 
    return data;
}

This generates a sitemap.xml file available at /sitemap.xml.

Example output:

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
	<url>
		<loc>http://localhost:3000</loc>
		<lastmod>2025-02-05T15:43:40.554Z</lastmod>
		<changefreq>yearly</changefreq>
		<priority>1</priority>
	</url>
	<url>
		<loc>http://localhost:3000/docs/deploy</loc>
		<lastmod>2025-01-28T13:54:42.000Z</lastmod>
		<changefreq>weekly</changefreq>
		<priority>0.6</priority>
	</url>
	...
</urlset>

All Fumadocs pages are automatically added to the sitemap.

On this page