Drop-in sitemap, robots.txt, llms.txt, metadata, JSON-LD, RSS feed, and static params — all auto-generated from CMS content via @webhouse/cms/next.
Overview
@webhouse/cms/next is a sub-path export that gives your Next.js site full SEO and discoverability — sitemap, robots.txt, llms.txt, metadata, JSON-LD, RSS feed — all auto-generated from CMS content and _seo fields.
No new logic needed. It wraps the existing CMS build pipeline for Next.js consumption.
# Already included with @webhouse/cms — no extra install
import { cmsSitemap, cmsRobots, cmsMetadata } from '@webhouse/cms/next';Sitemap
Auto-generates sitemap.xml with hreflang alternates for multi-locale sites.
// app/sitemap.ts
import { cmsSitemap } from '@webhouse/cms/next';
export default cmsSitemap({
baseUrl: 'https://example.com',
collections: [
{ name: 'pages', urlPrefix: '/' },
{ name: 'posts', urlPrefix: '/blog' },
],
// Optional i18n
locales: ['en', 'da'],
defaultLocale: 'en',
localeStrategy: 'prefix-other',
});Options:
| Option | Type | Default | Description |
|---|---|---|---|
baseUrl | string | — | Site URL (no trailing slash) |
collections | SitemapCollection[] | — | Collections to include |
locales | string[] | — | Available locales for hreflang |
defaultLocale | string | — | Default locale (gets x-default) |
localeStrategy | string | "prefix-other" | URL locale strategy |
changeFrequency | string | "weekly" | Default change frequency |
defaultPriority | number | 0.7 | Default priority |
Robots.txt
Generates robots.txt with AI bot management strategies from F112 GEO.
// app/robots.ts
import { cmsRobots } from '@webhouse/cms/next';
export default cmsRobots({
baseUrl: 'https://example.com',
strategy: 'maximum', // or 'balanced', 'restrictive', 'custom'
});Strategies:
| Strategy | Behavior |
|---|---|
maximum | Allow all bots including AI crawlers |
balanced | Allow search engines, block aggressive AI scrapers |
restrictive | Block all AI bots, allow only search engines |
custom | Your own rules via customRules |
llms.txt
Machine-readable site index for AI agents — helps AI crawlers understand your site structure.
// app/llms.txt/route.ts
import { cmsLlmsTxt } from '@webhouse/cms/next';
export const GET = cmsLlmsTxt({
baseUrl: 'https://example.com',
siteTitle: 'My Site',
siteDescription: 'A great site built with webhouse.app',
collections: [
{ name: 'posts', label: 'Blog Posts', urlPrefix: '/blog' },
],
});For the full content export (all document text):
// app/llms-full.txt/route.ts
import { cmsLlmsFullTxt } from '@webhouse/cms/next';
export const GET = cmsLlmsFullTxt({
baseUrl: 'https://example.com',
siteTitle: 'My Site',
collections: [{ name: 'posts', label: 'Blog Posts', urlPrefix: '/blog' }],
});Metadata
Extracts _seo fields from any CMS document into a Next.js Metadata object.
// app/blog/[slug]/page.tsx
import { cmsMetadata } from '@webhouse/cms/next';
import { getDocument } from '@/lib/content';
export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
const doc = getDocument('posts', slug);
if (!doc) return {};
return cmsMetadata({
baseUrl: 'https://example.com',
siteName: 'My Site',
doc,
collection: 'posts',
urlPrefix: '/blog',
});
}What it generates:
titlefrom_seo.metaTitleordata.titledescriptionfrom_seo.metaDescriptionordata.excerptkeywordsfrom_seo.keywordsopenGraphwith image, site name, type (article/website), published timealternates.canonicalfrom_seo.canonicalor computed URLrobotsfrom_seo.robots- Geo meta tags from map fields (F96)
JSON-LD
Extracts structured data from _seo.jsonLd for search engine rich results.
// In your page component
import { cmsJsonLd } from '@webhouse/cms/next';
export default function BlogPost({ doc }) {
const jsonLd = cmsJsonLd(doc);
return (
<article>
{jsonLd && (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
)}
<h1>{doc.data.title}</h1>
</article>
);
}CMS admin generates JSON-LD from 12 schema templates (Article, BlogPosting, FAQ, Product, LocalBusiness, etc.) via the SEO panel.
RSS Feed
Auto-generates RSS 2.0 XML feed from CMS content.
// app/feed.xml/route.ts
import { cmsFeed } from '@webhouse/cms/next';
export const GET = cmsFeed({
baseUrl: 'https://example.com',
title: 'My Blog',
description: 'Latest posts from My Blog',
collections: [{ name: 'posts', urlPrefix: '/blog' }],
maxItems: 50,
});generateStaticParams
Factory for Next.js generateStaticParams() — returns all published slugs for a collection.
// app/blog/[slug]/page.tsx
import { cmsGenerateStaticParams } from '@webhouse/cms/next';
export const generateStaticParams = cmsGenerateStaticParams({
collection: 'posts',
paramName: 'slug', // default
});Fly.io Deployment
Next.js boilerplates include a production-ready Dockerfile for Fly.io deploy:
# Deploy via CLI
flyctl deploy --remote-only --ha=falseOr use the Deploy tab in CMS admin — it auto-detects the Dockerfile and deploys to Fly.io with:
- Region:
arn(Stockholm) - Port: 3000
- Memory: 512MB
- Auto-generated
fly.toml
The Dockerfile uses Next.js standalone output (output: "standalone" in next.config.ts) for minimal image size. Content files are copied into the image for fs-based reads at runtime.
Complete Setup
Here's what a fully SEO-optimized Next.js site looks like:
app/
sitemap.ts ← cmsSitemap()
robots.ts ← cmsRobots()
llms.txt/route.ts ← cmsLlmsTxt()
llms-full.txt/route.ts ← cmsLlmsFullTxt()
feed.xml/route.ts ← cmsFeed()
blog/
[slug]/page.tsx ← cmsMetadata() + cmsJsonLd()
[slug]/page.tsx ← cmsMetadata() + cmsJsonLd()All of this is pre-configured in both the nextjs-boilerplate and nextjs-github-boilerplate templates.