Skip to content
BetaDocs

SEO and indexing

Typeroll generates SEO metadata in the static build. Saved settings do not change a live website until it is published. The same content and rendering rules apply to Typeroll Cloud and self-hosting; the hosting provider can add response headers or access rules of its own.

Start with a Page’s Meta panel and the Site settings. Before launch, review the publication check report and the actual public URLs. Technical correctness does not guarantee indexing, rankings or traffic.

Output Value selection
Document title Page.seo_title, otherwise Page.title, with the configured suffix unless disabled for the Page
Description Page.seo_description, then default_meta_description, then the Site tagline
Sharing text Page.og_title / Page.og_description, otherwise the document title / description
Social image Page.og_image, then the public content-type image mapping, then default_og_image, then the Site logo
Social image alt Page.seo_image_alt, then the mapped image’s public <field>_alt field; explicit images retain the HTML-alt fallback
Language Page.language, otherwise the Site language, otherwise English

The renderer emits OpenGraph and Twitter card metadata alongside ordinary HTML metadata. Use specific descriptions for important Pages; a Site-wide fallback avoids empty output but does not make every description useful or unique.

A visible heading and a document title are different. Keep one H1 in the Page layout; a Page template can supply it from the Page title. Use H2 and H3 for the body structure, with visual sizing controlled independently of heading level.

The renderer resolves a Page’s route from its explicit path, Content type route pattern and hierarchy as applicable. It does not assume that a simple slug is the complete route. The Site’s trailing_slash policy determines the normal slash form.

The default canonical combines the resolved path with the publication’s website origin. An intentional Page.canonical_url overrides it, including for a cross-domain canonical. Configure that explicitly; do not add a second canonical through custom markup. The artifact validator checks canonical output against that configuration.

For current customer-owned publishing, the Hosting Group supplies the temporary site address base. A Site can later use its own website host. Creating a Site does not provision a permanent public typeroll.com subdomain.

Follow Website and media domains to prepare a verified build with the intended URLs before switching traffic. Current publishing separates preparation, verification and cutover. Merely entering a hostname is not proof that the new address is live. Older managed sites have a separate legacy domain workflow.

Section titled “Indexing and following links are independent”
Intended public behavior Page settings HTML robots value
Index the Page and follow its links Neither flag set index,follow
Keep the Page out of search, but follow its links noindex: true noindex,follow
Keep it out of search and request no link following noindex: true, nofollow: true noindex,nofollow

sitewide_noindex and sitewide_nofollow apply the corresponding restrictions across the Site. Private previews and versions configured with robots_blocked use strict restrictions; an ordinary Page flag does not override them.

A public noindex Page may remain internally linked. It is not a broken link simply because it is absent from the indexable sitemap. Noindex is not access control: use authenticated or expiring previews for private review, and never publish secrets in a noindex Page.

A normal build emits /robots.txt with a permissive default and references to /sitemap.xml and /sitemap-images.xml. settings.robots_txt supplies custom crawl rules; the renderer ensures the generated sitemap references are present. A version with robots_blocked instead emits Disallow: /.

settings.ai_crawler_policy adds a Content Signal and disallow groups for AI crawlers, in the vocabulary Cloudflare uses; the default adds nothing. See AI crawlers for the values, the agents each one lists, and how it interacts with a Cloudflare zone’s own AI bot policy.

Crawl permission in robots.txt and indexability in HTML are different settings. If you want a public Page crawled but excluded from results, use noindex; blocking fetches can prevent crawlers from reading that directive.

Hosting headers are a third layer. Managed fallback protection can emit host-scoped X-Robots-Tag: noindex, nofollow rules in the Cloudflare Pages _headers artifact. A matching fallback header can be stricter than the Page’s HTML. Self-hosted operators configuring a shared fallback namespace use SITES_BASE_DOMAIN; operators without it must verify their hosting policy. Do not assume that any arbitrary alias is protected just because the preferred hostname is configured.

Call check_site_indexing, or GET /api/v1/sites/{siteId}/indexing-diagnostics, before launch and after domain or indexing changes. It reports the recorded fallback and production roots, response headers, HTML robots and robots.txt separately. Also inspect provider firewall, bot and access settings when requests are blocked. An HTTP check does not prove how a verified search-engine crawler is treated.

In Core 0.2.88, expectation_reason explains the policy being checked. For customer publishing with no future website host saved, the platform’s robots_blocked protection intentionally requires noindex, even when sitewide_noindex is false. This is expected on the temporary address. Saving a future host changes the intended policy; publish the prepared candidate before expecting its output to reflect that change. A site’s own noindex setting remains independent, and an unexpected noindex on a public site still fails the check.

Supply date_published and date_updated as ISO 8601 timestamps with Z or an explicit offset, for example 2024-05-02T10:01:08Z. In Core 0.2.88, generated Article and Content type schema preserves that offset. A legacy local timestamp without a timezone is emitted at calendar-date precision instead of inventing an instant; invalid dates are omitted. To restore the exact time, correct the stored field from a trustworthy source timestamp and publish normally. This does not rewrite manually supplied JSON-LD or existing customer content.

A build emits:

  • /sitemap.xml: published, indexable Page routes using the publication’s origin and slash policy. Drafts, review content, unlisted Pages and noindex Pages are excluded. Site-wide or version indexing restrictions suppress entries. A Page with alternates also lists its hreflang cluster as xhtml:link entries. A site with more than 45,000 addresses gets a sitemap index at /sitemap.xml that points to /sitemap-1.xml, /sitemap-2.xml and so on.
  • /sitemap-images.xml: eligible Page image references, grouped by the resolved Page URL (including content-type routes and explicit paths). Includes public image fields such as a featured image, OG images, HTML body images and image fields in nested blocks, slots and Page templates. Responsive image sources and srcset candidates are included and duplicates are removed per Page. Drafts, unlisted Pages, noindex Pages, private fields and unused media-library files are excluded; a blocked preview/version or site-wide noindex produces an empty image sitemap. Each Page includes at most 1,000 image URLs. CSS-only backgrounds and client-generated images are not discovered. Rebuild the site after upgrading Core to regenerate this file; a portal update alone does not change an existing publication.
  • /llms.txt: a Markdown map of the site for AI assistants, following llmstxt.org. It lists published, listed, indexable Pages with titles, URLs and descriptions, grouped by Content type (using its plural label), with each language section in its own groups after the site language. It links the sitemap and /llms-full.txt.
  • /llms-full.txt: the Markdown of every Page in llms.txt, in the same order, in one file of at most about 1 MB. Pages past that size are listed as links to their own Markdown files.
  • <page>/index.md: a Markdown version of each Page in llms.txt, for example /about/index.md and /index.md for the home page. It holds the Page’s title, description, address, date, language, public custom fields and the text of its blocks: headings, paragraphs, lists, links, images with alt text, tables, and accordion questions with their answers. Layout, decoration, navigation, forms, embeds, custom HTML blocks and the header and footer are left out. Each Page announces its file with <link rel="alternate" type="text/markdown">.

The same rules apply to all three: unlisted and noindex Pages are left out, and a robots-blocked version or a site-wide noindex publishes no Markdown files and an llms.txt without Pages. They are discovery data, not authentication or a guarantee that an AI service will use them.

Page.lastmod_override can supply a sitemap date. An empty string suppresses lastmod; otherwise the renderer uses the available updated/published timestamp. Use a meaningful date rather than making unchanged content appear newly revised.

Inspect the generated artifact after importing HTML or changing media sources, especially when images are introduced by custom markup or scripts. Do not assume that syntactically valid XML establishes complete image coverage.

Output Configuration and scope
Organization Homepage only; Site organization, contact and social settings describe the website’s brand, not the Typeroll account
WebSite Homepage only; Site name, origin and optional tagline
Article Pages with kind: "article"; title, dates, author and available image/description
BreadcrumbList Non-home routes, using resolved breadcrumbs and the intended canonical for the final item
Content type schema The type’s schema_type, field mode and supported field map
FAQPage Pages whose Accordion blocks hold questions and answers (see FAQ from accordions)
Custom JSON-LD Explicit Page.json_ld, for information genuinely represented by that Page. FAQ, recipe and event pages: the structured data tools

The visible breadcrumbs and generated schema use resolved routes, including Content type prefixes. Do not paste a second BreadcrumbList to repair a route.

Content type schema_field_map supports direct properties only. For example, { "website": "url" } is supported; "address.addressLocality" is rejected rather than emitted as a literal dotted JSON key. Reserved prototype names are also rejected. Use schema_field_mode: "mapped" to restrict automatic output to explicitly mapped fields. Fields marked rendered: false remain private.

Page dates can be selected explicitly in mapped mode without including the body or unrelated custom fields:

{
"schema_type": "Article",
"schema_field_mode": "mapped",
"schema_field_map": {
"title": "headline",
"date_published": "datePublished",
"date_updated": "dateModified"
}
}

The two date sources read Page metadata, not similarly named custom fields. Missing or invalid dates are omitted; explicit timezone offsets are preserved. Mapped mode does not add articleBody, publisher or unmapped fields. Existing custom date-field mappings remain supported. Page date mapping is available from Core 0.2.121; republish static sites after upgrading.

For a Content type with schema_type Product or SoftwareApplication (including WebApplication, MobileApplication and VideoGame), map fields to flat properties and the renderer nests them the way schema.org expects:

  • price, priceCurrency, availability and priceValidUntil become an offers Offer, with the Page’s canonical URL. A price is required for the Offer.
  • ratingValue with ratingCount or reviewCount (and optional bestRating and worstRating) becomes an aggregateRating. A rating without a count is left out.
  • A plain brand name becomes a Brand.
{
"schema_type": "SoftwareApplication",
"schema_field_mode": "mapped",
"schema_field_map": {
"title": "name",
"summary": "description",
"os": "operatingSystem",
"category": "applicationCategory",
"price": "price",
"currency": "priceCurrency"
}
}

Without a map, Product and SoftwareApplication read the field names price, price_currency (or currency), rating, rating_count and review_count, and SoftwareApplication also operating_system and application_category. A field that already holds an offers or aggregateRating object is published as it is.

A Page whose Accordion blocks hold questions and answers gets FAQPage JSON-LD automatically. An accordion counts only when every item’s title ends with a question mark (?, ? or ؟) and has a nonempty answer, so a specification list in an accordion is not marked up as FAQ. Answers are published as plain text. Only the published page body is read: an accordion in a hidden condition branch, the header or the footer is not included.

When the Page’s json_ld or its Content type schema already declares FAQPage, nothing is added, so the type is never emitted twice. To mark up FAQ content that is not in an accordion, use add_faq_schema.

A Site’s structured contact address uses street_address, postal_code, address_locality, address_region and address_country. The renderer converts these to Schema.org’s PostalAddress keys in the homepage Organization object. A plain address string is not expanded into invented structured fields. For more complex Page-specific graphs, author and review explicit JSON-LD.

The renderer prepares the page body for a fast largest paint:

  • Images. The first two content images load eagerly, and get fetchpriority="high" unless they set their own priority, even when a block template marks its image loading="lazy". Later images load lazily. Logo blocks, images inside logo links and images of 96×96 px or smaller do not count as the first images. An image is never both lazy and high priority.
  • Backgrounds. When the page’s first section shows a background image (a Section or container background, a Hero in the full-image layout, or a Call to action with its image as background), the head preloads it with <link rel="preload" as="image" fetchpriority="high">. A background further down the page is not preloaded.
  • Fonts. The theme’s heading, body and mono fonts load once, without blocking rendering. Custom CSS or scripts_head that loads a theme font again is reported by the publication checks rather than removed, since its weights or styles may differ from the theme’s.

These rules apply when the site is published again; an already published site is not rewritten.

Declare equivalents with Page.alternates, using the public final URLs and language tags. The renderer adds the Page’s self-reference when a cluster exists. Keep the cluster reciprocal across the participating Pages. x-default can identify a language selector or fallback. Use Page.language when the Page’s language differs from the Site default.

Do not generate alternate URLs from a slug alone; equivalent content can have different paths on different sites. Invalid tags and non-absolute alternate URLs are rejected when saved.

Artifact checks inspect the actual HTML, routes, redirects, JSON-LD, sitemaps and robots settings before activation. Blocking technical errors leave the current live site intact. Editorial warnings require review; they do not authorize automatic copy changes.

Problem First checks
Wrong canonical host Publication origin, explicit Page override and whether the domain candidate was successfully activated
Missing sitemap entry Page status, route availability, Page/Site noindex and version restrictions
Public Page unexpectedly noindex HTML robots, response headers and selected version; inspect them separately
Wrong breadcrumb path Parent Pages, Content type route and explicit Page path; do not duplicate schema
Stale metadata after an edit Saved content, the deployment result and the served artifact
Duplicate descriptions or awkward titles Review the reported Pages and edit their content deliberately

On an older installation, update the matching Core and shared build engine before relying on newer validation behavior. Updating MCP alone cannot change the renderer. The source renderer and the publication-check guide describe the technical contract and its limitations.

From Core 0.2.120 / MCP 0.45.90, Meta → Sharing title and Sharing description control OpenGraph and Twitter text independently of the search title and description. API/MCP agents set Page og_title and og_description; empty values restore the SEO fallback.

The sharing image uses Page og_image, then a public content-type field mapped to image in schema_field_map, then the site’s default_og_image, then its logo. For a mapped field such as featured_image, its public featured_image_alt field provides the description. seo_image_alt overrides that description. Private (rendered: false) fields are never exposed.

Social networks do not show SVG, AVIF or TIFF share images. When the selected image is one of these and comes from the site’s media library, the publication build renders a 1200×630 PNG copy and points og:image and twitter:image at it. The image is contained, never cropped, on the theme’s background colour, and the copy is published at /_assets/share/. The original stays the page image everywhere else. A raster share image from the media library also gets og:image:type, og:image:width and og:image:height. For the best card, choose a 1200×630 PNG or JPEG as default_og_image and as Page images.

Language-only tags use a likely region (sv → sv_SE); explicit regions are preserved (de-AT → de_AT, en-GB → en_GB). Changes require a new site publication; updating Typeroll does not rewrite an already published site.

WordPress import preserves helper/Yoast OpenGraph titles and descriptions. Existing imports are not rewritten. Compare source and target full HTML with the starter’s scripts/typeroll/compare_seo.py, review differences and restore verified source values through update_page before publishing.