@paragraphcms/seo
v0.2.2
Published
SEO document generators for Paragraph CMS sites.
Maintainers
Readme
@paragraphcms/seo
SEO document generators for Paragraph CMS sites.
@paragraphcms/seo builds robots.txt, sitemap.xml, rss.xml, and llms.txt from a single Client instance from @paragraphcms/client plus your route definitions.
Install
npm install @paragraphcms/client @paragraphcms/seo
# or
pnpm add @paragraphcms/client @paragraphcms/seo
# or
yarn add @paragraphcms/client @paragraphcms/seo
# or
bun add @paragraphcms/client @paragraphcms/seoQuick Start
import { Client } from "@paragraphcms/client";
import {
SEO,
localizedContentRoute,
localizedRoute,
} from "@paragraphcms/seo";
const client = new Client({
apiKey: process.env.PARAGRAPH_API_KEY!,
});
const seo = new SEO({
client,
site: {
url: "https://example.com",
name: "My site",
description: "Latest posts from my site.",
defaultLocale: "en",
},
routes: {
home: localizedRoute(),
blog: localizedContentRoute("blog", {
params: {
collection: "blog",
},
}),
features: localizedContentRoute("features", {
params: {
collection: "features",
},
}),
},
});
const robots = await seo.robotsTxt();
const sitemap = await seo.sitemapXml();
const blogRss = await seo.rssXml({
locale: "en",
route: "blog",
});
const llms = await seo.llmsTxt();Default Locale
If you do not pass site.defaultLocale, the library resolves it with client.locales.getDefaultLocale().
site.defaultLocale always wins when both are available.
rssXml() and llmsTxt() use the resolved default locale when locale is omitted.
Route Params
Each content route lives directly under routes, and you can attach filtering params right there:
import {
localizedContentRoute,
localizedRoute,
} from "@paragraphcms/seo";
routes: {
home: localizedRoute(),
blog: localizedContentRoute("blog", {
params: {
collection: "Blog",
},
}),
features: localizedContentRoute("features", {
params: {
collection: "Features",
},
}),
}params is forwarded to client.pages.list() for that route, with language and requiredSlug filled in automatically by the library.
published defaults to true for every content route. If you need unpublished entries for a specific route, override it with published: false.
The Paragraph client also supports status filters in pages.list(), so you can pass statusId or statusType in params when needed.
If you prefer plain objects, content routes also support basePath directly:
routes: {
home: localizedRoute(),
blog: {
basePath: "blog",
params: {
collection: "Blog",
},
},
}basePath: "blog" expands to /blog for the default locale and /:locale/blog for other locales. Post URLs are generated automatically by appending the page slug.
Localized Route Helpers
localizedRoute() returns a function, so this:
home: localizedRoute(),is equivalent to writing:
home: ({ locale, defaultLocale }) =>
locale === defaultLocale ? "/" : `/${locale}`,Pass a path when you want a localized non-root route:
const docsRoute = localizedRoute("docs");RSS
If you configure more than one content route, pass route to rssXml():
const rss = await seo.rssXml({
locale: "en",
route: "features",
});Artifact Paths
You can override the public paths used inside generated documents:
const seo = new SEO({
client,
site,
routes,
artifacts: {
sitemapPath: "/sitemap.xml",
robotsPath: "/robots.txt",
llmsPath: "/llms.txt",
rssPath: ({ locale, route, collection, defaultLocale }) =>
locale === defaultLocale
? `/${route}-${collection?.toLowerCase()}.xml`
: `/${locale}/${route}-${collection?.toLowerCase()}.xml`,
},
});API
new SEO(options)
Creates an instance with four async methods:
robotsTxt()sitemapXml()rssXml({ locale?, route? })llmsTxt({ locale? })
License
MIT
