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.
Titles, descriptions and social previews
Section titled “Titles, descriptions and social previews”| 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.
Routes and canonicals
Section titled “Routes and canonicals”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.
Indexing and following links are independent
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.
robots.txt and hosting headers
Section titled “robots.txt and hosting headers”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.
Publication dates
Section titled “Publication dates”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.
Sitemaps and agent discovery
Section titled “Sitemaps and agent discovery”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 withalternatesalso lists its hreflang cluster asxhtml:linkentries. A site with more than 45,000 addresses gets a sitemap index at/sitemap.xmlthat points to/sitemap-1.xml,/sitemap-2.xmland 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 andsrcsetcandidates 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 inllms.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 inllms.txt, for example/about/index.mdand/index.mdfor 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.
Structured data
Section titled “Structured data”| 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.
Products and software
Section titled “Products and software”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,availabilityandpriceValidUntilbecome anoffersOffer, with the Page’s canonical URL. A price is required for the Offer.ratingValuewithratingCountorreviewCount(and optionalbestRatingandworstRating) becomes anaggregateRating. A rating without a count is left out.- A plain
brandname becomes aBrand.
{ "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.
FAQ from accordions
Section titled “FAQ from accordions”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.
Image loading and first paint
Section titled “Image loading and first paint”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 imageloading="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_headthat 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.
Language alternatives
Section titled “Language alternatives”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.
Publication checks and troubleshooting
Section titled “Publication checks and troubleshooting”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.
Sharing metadata
Section titled “Sharing metadata”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.