prelo
Plugins / SEO essentials

SEO essentials

Sitemap, robots.txt and canonical tags generated from your pages automatically.

Agithub.com/anderdigitalInfrastructureprelo >= 0.3Updated Apr 2026Official
Use this plugin
1
2
or point your agent at the spec:
Your agent reads the spec and writes the code into your project. Review the diff like any change.

What this adds

The technical SEO baseline every site needs and nobody wants to maintain by hand: an XML sitemap built from your published content, a sane robots.txt, and correct canonical + Open Graph tags on every page. When the client publishes or unpublishes in Studio, the sitemap follows.

How it works

The CMS already knows every public URL — this plugin teaches your frontend to expose that knowledge. Your agent adds sitemap and robots handlers that read the content API, and a small head-tags helper used by every page template. Nothing is hardcoded: add a content type later and it joins the sitemap by reading the schema.

The spec your agent followsexpand ▾
You are adding sitemap/robots/canonical support to a Prelo project. Read `prelo docs api` first. The site's public origin must come from one place — use an existing `SITE_URL` env/config value or introduce one.

1. **URL inventory helper.** Create a shared server-side helper `getPublicUrls()`:
   - Read `GET {CMS_URL}/api/schema` to enumerate types; for each public type the frontend routes (at minimum `page` and `post`), fetch published entries (`per_page=200`, paginate) and map them to absolute URLs using the frontend's actual route patterns.
   - Include each entry's `updated_at`/`published_at` for `<lastmod>`.
   - Include the homepage and any static routes the frontend defines.

2. **Sitemap.** Serve `GET /sitemap.xml` from the frontend:
   - Next.js: `app/sitemap.js` returning the array from `getPublicUrls()`.
   - Astro: an `src/pages/sitemap.xml.ts` endpoint rendering the XML.
   - One-process Prelo site (`config.site` / `web/site.js`): handle the `/sitemap.xml` path inside `handle(url)` and return `{ html }` with an XML content workaround only if the site module supports content types; otherwise prefer a custom route `"GET /sitemap"` is wrong (custom routes mount under `/api/x/`) — for one-process sites, generate `sitemap.xml` as a static file at build/deploy time instead and serve it from the web root.
   - Escape XML entities in URLs.

3. **robots.txt.** Serve `GET /robots.txt`: allow all, plus `Sitemap: {SITE_URL}/sitemap.xml`. If the CMS runs on a separate public hostname, disallow crawling of it entirely there (`/studio`, `/api`, `/uploads` excepted for images if desired).

4. **Head tags helper.** Create `seoTags(entry)` used by every page/post template. It must emit:
   - `<title>` and meta description from the entry's `seo` field group when present (`fields.seo.metaTitle` / `metaDescription`), falling back to the entry title and a truncated body excerpt (~155 chars, tag-stripped).
   - `<link rel="canonical">` — the entry's `seo.canonical` if set, else the page's own absolute URL. Never emit a canonical pointing at a draft or preview URL.
   - `noindex` robots meta when `seo.noindex` is true.
   - Open Graph + Twitter card tags: `og:title`, `og:description`, `og:url`, `og:type` (`article` for posts, `website` otherwise), and `og:image` from `seo.ogImage` or the entry's first image field/block, made absolute against `SITE_URL`.
   - Wire it into every template; remove any hand-written duplicate tags it replaces.

5. **One H1 discipline.** While editing templates, verify each template renders exactly one `<h1>` (the entry title). Fix any that render more.

6. **Verify.** Run `prelo audit <site-url>` if available (it runs the technical SEO checklist and prints JSON), or manually: fetch `/sitemap.xml` (valid XML, published URLs only), `/robots.txt`, and view-source one page and one post to confirm canonical + OG tags.

After it's built

Nothing for the site owner to do. Publish a page — it's in the sitemap. Set a meta title or the noindex toggle in Studio's SEO fields — the tags follow. Search Console can be pointed straight at /sitemap.xml.