SEO para sites GenPM: metadados com canônica e hreflang, sitemaps em partes, robots.txt, llms.txt e JSON-LD seguro
Instalar
genpm add @core/seoO que você recebe
- Código em src/lib/seo/, 9 arquivos. (20,8 kB)
- Regras de IA em src/lib/seo/AGENTS.md, mais arquivos de regras da IDE.
- Variáveis de ambiente adicionadas ao .env.example: SITE_URL, SEO_NOINDEX.
- Resolve @core/contracts, @core/site para você.
README
Este pacote não tem README.
Isto é exatamente o que sua IA lê quando trabalha em src/lib/seo. Nada mais é adicionado ao contexto dela.
@core/seo — rules for AI agents
Purpose
Everything search engines and crawling agents read: page metadata with site defaults (title template, description,
canonical, hreflang, Open Graph, Twitter, robots), a sitemap index with chunks of 50,000 URLs built from any
registered SitemapSource, robots.txt, llms.txt and schema.org JSON-LD builders with script-safe escaping.
No tables. OG image generation is out of scope for 1.0.
Map
index.ts— public API:buildMetadata,metaTags,SeoFieldsSchema,jsonLd,jsonLdScript,registerSitemapSource,robotsTxt,llmsTxt.metadata.ts,jsonld.ts,sitemap.ts,url.ts(SITE_URLhelpers).adapters/hono.ts—seoRoutes().adapters/next.ts—sitemapIndexRoute,sitemapChunkRoute,robotsRoute.
Integration
- Env:
SITE_URL(https). In staging setSEO_NOINDEX=1(noindex everywhere andDisallow: /). - Register sources in
src/genpm/seo.ts, imported at startup:registerSitemapSource(contentSitemapSource('pages', ({ slug }) =>/${slug})). - Routes: Hono
app.route('/', seoRoutes()). Next.js:app/sitemap.xml/route.ts,app/sitemaps/[name]/[file]/route.tsandapp/robots.txt/route.tsre-exporting the handlers (seeadapters/next.ts), each withexport const dynamic = 'force-dynamic'(otherwisenext buildprerenders them and needs the database andSITE_URLat build time); delete Next's ownsitemap.ts/robots.tsif present. - Pages: Next.js
export async function generateMetadata() { return buildMetadata({ title, description, path, alternates }) }; other frameworks putmetaTags(await buildMetadata(...))in<head>. - JSON-LD:
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: jsonLdScript(jsonLd.product(...)) }} />(jsonLdScriptescapes it, so this is the one safe use of raw HTML). - Add
seo: SeoFieldsSchemato collections that need per-entry overrides. - Verify:
/sitemap.xmllists chunks, each chunk lists published URLs; page<head>has one canonical.
Conventions
- One
buildMetadataper page; don't set<title>or description elsewhere. - Canonical paths are the public URL without query strings; pass
alternatesfor every translated page. noindexpreviews, internal search results and account pages.
Don't
- Don't add ratings, prices or availability to JSON-LD that the page doesn't show or that aren't real.
- Don't serialize JSON-LD with plain
JSON.stringifyinside a script tag. - Don't list drafts or private pages in a sitemap source.
# @core/seo — rules for AI agents
## Purpose
Everything search engines and crawling agents read: page metadata with site defaults (title template, description,
canonical, hreflang, Open Graph, Twitter, robots), a sitemap index with chunks of 50,000 URLs built from any
registered `SitemapSource`, `robots.txt`, `llms.txt` and schema.org JSON-LD builders with script-safe escaping.
No tables. OG image generation is out of scope for 1.0.
## Map
- `index.ts` — public API: `buildMetadata`, `metaTags`, `SeoFieldsSchema`, `jsonLd`, `jsonLdScript`, `registerSitemapSource`, `robotsTxt`, `llmsTxt`.
- `metadata.ts`, `jsonld.ts`, `sitemap.ts`, `url.ts` (`SITE_URL` helpers).
- `adapters/hono.ts` — `seoRoutes()`. `adapters/next.ts` — `sitemapIndexRoute`, `sitemapChunkRoute`, `robotsRoute`.
## Integration
1. Env: `SITE_URL` (https). In staging set `SEO_NOINDEX=1` (noindex everywhere and `Disallow: /`).
2. Register sources in `src/genpm/seo.ts`, imported at startup:
`registerSitemapSource(contentSitemapSource('pages', ({ slug }) => `/${slug}`))`.
3. Routes: Hono `app.route('/', seoRoutes())`. Next.js: `app/sitemap.xml/route.ts`, `app/sitemaps/[name]/[file]/route.ts`
and `app/robots.txt/route.ts` re-exporting the handlers (see `adapters/next.ts`), each with `export const dynamic = 'force-dynamic'`
(otherwise `next build` prerenders them and needs the database and `SITE_URL` at build time); delete Next's own `sitemap.ts`/`robots.ts` if present.
4. Pages: Next.js `export async function generateMetadata() { return buildMetadata({ title, description, path, alternates }) }`;
other frameworks put `metaTags(await buildMetadata(...))` in `<head>`.
5. JSON-LD: `<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: jsonLdScript(jsonLd.product(...)) }} />`
(`jsonLdScript` escapes it, so this is the one safe use of raw HTML).
6. Add `seo: SeoFieldsSchema` to collections that need per-entry overrides.
7. Verify: `/sitemap.xml` lists chunks, each chunk lists published URLs; page `<head>` has one canonical.
## Conventions
- One `buildMetadata` per page; don't set `<title>` or description elsewhere.
- Canonical paths are the public URL without query strings; pass `alternates` for every translated page.
- `noindex` previews, internal search results and account pages.
## Don't
- Don't add ratings, prices or availability to JSON-LD that the page doesn't show or that aren't real.
- Don't serialize JSON-LD with plain `JSON.stringify` inside a script tag.
- Don't list drafts or private pages in a sitemap source.
A árvore exata que será injetada, após o .genpmignore. Fixada em
// Adaptador Next.js (route handlers):
// app/sitemap.xml/route.ts → export { sitemapIndexRoute as GET } from '@/lib/seo/adapters/next';
// app/sitemaps/[name]/[file]/route.ts → export { sitemapChunkRoute as GET } from '@/lib/seo/adapters/next';
// app/robots.txt/route.ts → export { robotsRoute as GET } from '@/lib/seo/adapters/next';
// En los tres, añade `export const dynamic = 'force-dynamic'` (si no, `next build` los prerenderiza con BD y SITE_URL).
// Metadatos: `export async function generateMetadata() { return buildMetadata({ title, path }) }`.
import { robotsTxt, sitemapChunkXml, sitemapIndexXml } from '../index.ts';
const XML = { 'content-type': 'application/xml; charset=utf-8', 'cache-control': 'public, max-age=3600' };
export async function sitemapIndexRoute(): Promise<Response> {
return new Response(await sitemapIndexXml(), { headers: XML });
}
export async function sitemapChunkRoute(_req: Request, ctx: { params: Promise<{ name: string; file: string }> }): Promise<Response> {
const { name, file } = await ctx.params;
const m = /^(\d{1,4})\.xml$/.exec(file);
const body = m ? await sitemapChunkXml(name, Number(m[1])) : null;
return body ? new Response(body, { headers: XML }) : new Response('Not found', { status: 404 });
}
export function robotsRoute(): Response {
return new Response(robotsTxt(), { headers: { 'content-type': 'text/plain; charset=utf-8', 'cache-control': 'public, max-age=3600' } });
}
Este pacote não declara servidores MCP.
| Versão | Commit | Publicado | Análise |
|---|---|---|---|
| 1.0.0 | cf4e3c3 | há 5 horas | análise aprovada |
- npm
- zod ^4.0.0
- proposto
- O GenPM propõe o comando npm e só o executa se você disser sim.
- Usado por (1)
- @core/kit-cms ^1.0.0
- análise
- análise aprovada · 0 achados
- commit
- v1.0.0 → cf4e3c3ab3bbd5919dece315446321a20909599f · verificado após o download
- scripts
- Nenhum. O GenPM nunca executa código de pacotes.
- licença
- MIT
- Qualidade
- 100/100
- Licença reconhecidacumprido
- AGENTS.md explica o propósitocumprido
- AGENTS.md tem passos de integraçãocumprido
- AGENTS.md lista convenções ou proibiçõescumprido
- Inclui testescumprido
- Escaneamento de segurança aprovadocumprido
- Publicado nos últimos 6 mesescumprido
- Publicador verificadocumprido
- Resumo e palavras-chavecumprido
- denúncia
- Viu algo errado?