Skip to content

Metadata

This document covers the metadata system within the ShipSaaS template and guides you on how to customize SEO settings.

The ShipSaaS template has a built-in metadata system that provides:

  • SEO-optimized page titles and descriptions
  • Social media sharing metadata (Open Graph and Twitter Cards)
  • Website icons and application branding (Logo and Favicon)

Metadata in ShipSaaS is configured through several key files:

The primary website settings are defined in src/config/website.ts:

src/config/website.ts

import { messages } from '@/messages';
export const websiteConfig: WebsiteConfig = {
metadata: {
name: messages.site.name,
title: messages.site.title,
description: messages.site.description,
images: {
ogImage: '/og.png',
logoLight: '/logo.webp',
logoDark: '/logo-dark.png',
},
},
social: {
github: 'https://github.com/ShipSaaS',
twitter: 'https://x.com/ShipSaaS',
youtube: 'https://www.youtube.com/@ShipSaaS',
},
// Other configuration sections...
};

This configuration defines:

  • The website’s name, title, and description
  • Logo and Open Graph image paths
  • Official account links for social platforms

Basic website metadata (such as name, title, and description) is defined in message localization files:

src/messages/en.ts

export const messages = {
site: {
name: 'ShipSaaS',
title: 'ShipSaaS - The Best SaaS Boilerplate',
description: 'ShipSaaS is a full-stack SaaS boilerplate...',
},
// other messages...
} as const;

src/messages/zh.ts

export const messages = {
site: {
name: 'ShipSaaS',
title: 'ShipSaaS - 快速构建 SaaS 产品',
description: 'ShipSaaS 是一个使用最先进技术栈构建的 SaaS 模板...',
},
// other messages...
} as const;

To switch the currently used language, edit src/messages/index.ts to re-export the target language file.

The seo() function in src/lib/seo.ts constructs metadata and canonical links for each page:

src/lib/seo.ts

export function seo(
path: string,
options: {
title: string;
description?: string;
keywords?: string;
image?: string;
type?: 'website' | 'article';
}
) {
const url = getCanonicalUrl(path);
const image = options.image ?? getOgImage();
return {
meta: metadata({ ...options, url, image, type: options.type ?? 'website' }),
links: [{ rel: 'canonical', href: url }],
};
}

This function handles:

  • Setting page titles and descriptions
  • Configuring Open Graph and Twitter Card metadata
  • Setting canonical URLs
  • Generating OG image URLs

Each route defines its metadata via the head() function in createFileRoute:

src/routes/index.tsx

import { createFileRoute } from '@tanstack/react-router';
import { seo } from '@/lib/seo';
export const Route = createFileRoute('/')({
head: () => ({
...seo('/', {
title: 'ShipSaaS - Home',
description: 'Welcome to ShipSaaS',
}),
}),
component: HomePage,
});

The root route (src/routes/__root.tsx) defines global metadata, including charset, viewport, website icons, and default title/description:

src/routes/__root.tsx

export const Route = createRootRouteWithContext<{
queryClient: QueryClient;
}>()({
head: () => ({
meta: [
{ charSet: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ title: websiteConfig.metadata?.title },
{ name: 'description', content: websiteConfig.metadata?.description },
],
links: [
{ rel: 'apple-touch-icon', sizes: '180x180', href: '/apple-touch-icon.png' },
{ rel: 'icon', type: 'image/png', sizes: '32x32', href: '/favicon-32x32.png' },
{ rel: 'icon', type: 'image/png', sizes: '16x16', href: '/favicon-16x16.png' },
{ rel: 'icon', href: '/favicon.ico' },
{ rel: 'manifest', href: '/manifest.json' },
],
}),
// ...
});

To change basic website information (such as name, title, and description), edit the active language message file:

src/messages/en.ts

export const messages = {
site: {
name: 'Your Website Name',
title: 'Your Website Title - Catchy Tagline',
description: 'Detailed description of your website for SEO purposes',
},
// ...
} as const;

To change the Open Graph image and Logo:

  1. Place your image files in the public directory.
  2. Update the paths in src/config/website.ts:

src/config/website.ts

metadata: {
// Other settings...
images: {
ogImage: '/your-og-image.png', // For social sharing
logoLight: '/your-logo-light.png', // Light mode Logo
logoDark: '/your-logo-dark.png', // Dark mode Logo
},
}

Recommended dimensions:

  • OG Image: 1200×630 pixels for optimal display across social platforms.
  • Logo: At least 512×512 pixels for high-resolution displays.

Update your official social media profile links in the website configuration:

src/config/website.ts

social: {
github: 'https://github.com/YourUsername',
twitter: 'https://x.com/YourHandle',
youtube: 'https://www.youtube.com/@YourChannel',
},

To replace the default favicons and app icons:

  1. Generate a complete icon set using tools like Real Favicon Generator.
  2. Place the generated files in the public directory.
  3. The root route will automatically link these files.

In each route, use the seo() helper function within head() to define page-specific metadata:

export const Route = createFileRoute('/about')({
head: () => ({
...seo('/about', {
title: 'About Us',
description: 'Learn more about our team and mission',
image: '/images/about-og.png',
}),
}),
component: AboutPage,
});

Blog posts utilize frontmatter metadata which is applied automatically:

content/blog/example-post.md

---
title: Example Blog Post
description: This is an example blog post with custom metadata
image: https://example.com/images/blog/example-post.png
date: "2024-01-01"
category: tutorial
---
Content here...
  • Keep Titles Concise: Target titles under 60 characters for optimal rendering in search results.
  • Write Descriptive Meta Descriptions: Craft compelling descriptions of 150-160 characters.
  • Use High-Quality Images: Create professional, context-appropriate images for Open Graph and Twitter Cards.
  • Incorporate Keywords Naturally: Naturally integrate relevant keywords in titles and descriptions.
  • Stay Updated: Ensure your metadata updates dynamically along with content revisions.
  • Mobile Optimization: Double-check how your metadata previews look on mobile viewport widths.

Now that you know how to customize metadata in ShipSaaS, explore these related topics: