Features

SEO & Analytics

Configure page metadata, Open Graph images, sitemaps, robots.txt, and Google Analytics tracking.

MoveFast includes a complete SEO system, machine-readable public content, and optional Google Analytics integration. Public pages get canonical metadata, social sharing data, structured data, and deliberate crawl directives out of the box.

Metadata System

MoveFast uses Next.js built-in metadata API with a helper function that generates consistent SEO tags across all pages.

How It Works

The createMetadata() function in src/lib/seo/metadata.ts generates:

  • Page title (with site name template)
  • Meta description
  • Keywords
  • Canonical URL
  • Open Graph tags (title, description, image, type)
  • Twitter Card tags
  • Robots directives (index/noindex)
  • Google preview controls for large images and complete snippets
  • RSS, Atom, and JSON Feed discovery links

Per-Page Metadata

Each page exports metadata using the helper:

typescript
import { createMetadata } from "@/lib/seo/metadata";
 
export const metadata = createMetadata({
    title: "Your Page Title",
    description: "A description for search engines and social sharing.",
    path: "/your-page",
    keywords: ["keyword1", "keyword2"],
});

Available Options

typescript
interface SEOConfig {
    title: string;           // Page title
    description: string;     // Meta description
    path?: string;           // URL path (for canonical URL)
    keywords?: readonly string[]; // SEO keywords
    image?: string;          // OG image URL (defaults to /og-image.svg)
    noIndex?: boolean;       // Set true to hide from search engines
    type?: "website" | "article" | "profile"; // OG type
    publishedTime?: string;  // For blog articles
    modifiedTime?: string;   // For blog articles
    authors?: string[];      // For blog articles
}

Pre-Built Page Metadata

Common pages already have metadata configured via pageMetadata:

typescript
import { pageMetadata } from "@/lib/seo/metadata";
 
// Use in your page:
export const metadata = pageMetadata.pricing();
export const metadata = pageMetadata.blog();
export const metadata = pageMetadata.contact();

Open Graph Image

The default OG image is at public/og-image.svg. This is the image shown when your site is shared on Twitter, LinkedIn, Facebook, etc.

To replace it:

  1. Create a 1200x630 image
  2. Save it as public/og-image.svg (or any name)
  3. If using a different filename, update DEFAULT_OG_IMAGE in src/lib/seo/metadata.ts

Sitemap

MoveFast auto-generates a sitemap at /sitemap.xml. It includes:

  • All public pages (home, pricing, contact, etc.)
  • All published blog posts
  • All published documentation pages

The sitemap is generated at build time by Next.js from src/app/sitemap.ts.

Only canonical, indexable pages belong in the sitemap. Private account routes and legal pages marked noIndex are intentionally excluded. Blog entries use their published date as lastModified; static pages do not claim a new modification date on every build.


Robots.txt

The robots.txt file at /robots.txt tells search engines what to crawl. It is generated from src/app/robots.ts and:

  • Allows all crawlers on public pages
  • Blocks crawling of admin, auth, profile, and billing routes
  • Allows the public /api/ai snapshot and Markdown content endpoints
  • Explicitly allows search and user-requested crawlers such as OAI-SearchBot and Claude-SearchBot
  • Blocks the listed model-training crawlers by default; change the TRAINING_BOTS rule if your policy is different
  • Points to the sitemap URL

Structured Data

MoveFast renders JSON-LD that matches visible page content:

  • Organization and WebSite entities in the root layout
  • WebPage, SoftwareApplication, and FAQPage entities on the home page
  • CollectionPage and ItemList data on the blog index
  • BlogPosting and BreadcrumbList data on each article
  • TechArticle and BreadcrumbList data on documentation pages

The builders live in src/lib/seo/structured-data.ts. The JsonLd component escapes < characters before rendering JSON so content cannot break out of the script tag.

Keep structured data aligned with what a visitor can actually see. Do not add reviews, ratings, prices, or features that are not present on the corresponding page.


AI and Agent Discovery

The HTML pages remain the canonical source. The additional discovery endpoints make the same public information easier for agents and feed readers to retrieve:

EndpointPurpose
/llms.txtConcise site identity and curated first-party content map
/llms-full.txtCombined public documentation and blog context
/ai.txtRetrieval, attribution, freshness, and restricted-route guidance
/api/aiBounded JSON snapshot of public pages and recent content
/api/md/docs/[slug]Clean Markdown for a published documentation page
/api/md/blogs/[slug]Clean Markdown for a published blog article
/.well-known/api-catalogMachine-readable catalog of public discovery endpoints and feeds

These files supplement normal SEO. They do not replace crawlable HTML, internal links, accurate metadata, or useful first-party content.

The global HTTP Link header in next.config.ts advertises the discovery files and feeds without adding route-specific client code.


Blog Feeds

Published blogs are available as:

  • RSS at /blogs/rss.xml
  • Atom at /blogs/atom.xml
  • JSON Feed at /blogs/feed.json

All three feeds are generated from the same MDX frontmatter used by the blog pages, so titles, dates, excerpts, authors, and canonical URLs stay synchronized.


Google Analytics

MoveFast supports Google Analytics 4 (GA4) through a dedicated component.

Setup

  1. Create a GA4 property at analytics.google.com
  2. Get your Measurement ID (starts with G-)
  3. Add it to your environment:
env
NEXT_PUBLIC_GA_MEASUREMENT_ID=G-XXXXXXXXXX

That is it. The analytics script loads automatically on all pages.

How It Works

The GoogleAnalytics component in src/components/analytics/GoogleAnalytics.tsx injects the GA4 script tag in the root layout. It only loads when NEXT_PUBLIC_GA_MEASUREMENT_ID is set and non-empty.

Disabling Analytics

To disable analytics (e.g., in development), simply do not set the NEXT_PUBLIC_GA_MEASUREMENT_ID variable, or leave it empty.


Page Titles

The root layout sets a title template:

typescript
title: {
    default: "MoveFast",
    template: "%s | MoveFast",
}

This means:

  • The home page title is just "MoveFast"
  • Other pages are formatted as "Page Title | MoveFast"

To change the site name, update WEBSITE.NAME in src/constants/website.ts.


Legal Pages and noIndex

Legal pages (privacy policy, terms of service, cookie policy) are marked as noIndex: true so search engines do not index them. This keeps your search results clean and focused on product pages.

typescript
export const metadata = createMetadata({
    title: "Privacy Policy",
    description: "...",
    noIndex: true,  // Won't appear in search results
});

Blog SEO

Blog posts get full article-type metadata and matching BlogPosting JSON-LD including:

  • Published date
  • Modified date
  • Author name
  • Article-specific OG type
  • Featured image as OG image

This is handled automatically from the blog post frontmatter (title, description, date, author, image fields).


Tips

  • Always set unique title and description for every page. Duplicate metadata hurts rankings.
  • Keep descriptions concise, specific, and accurate; search engines may display a different snippet when it better answers the query.
  • Use descriptive, keyword-rich titles but keep them natural.
  • Replace the default OG image with something branded. It is the first thing people see when your link is shared.
  • Submit your sitemap to Google Search Console after deploying for faster indexing.
  • Keep NEXT_PUBLIC_WEBSITE_URL set to the production origin so canonical URLs, feeds, and structured data never point to localhost.