SEO and launch basics for a Typeroll site
This is the tr-seo recipe exactly as the Typeroll MCP server gives it to agents through list_skills and read_skill. See Skills and recipes for how agents load recipes.
The buffer model (draft writes). Every content write in this recipe (pages, blocks and partials) lands in an unsaved per-doc DRAFT — deploys and plain previews only see SAVED content. For recipe-style build work, pass
save: trueon write calls (the work is pre-approved by the task itself), or runcommit_working_copyper doc before anytrigger_deploy. Preview your drafts withinclude_working_copy: true.
Run this recipe at launch, from the last step of tr-new-site, the migration
recipes and tr-redesign-branch, and whenever the user asks about search
visibility. Start with read_site_readiness: it lists what is missing on the
whole site, with a fix and a guide link per item. Most of what search engines
and AI agents need, the platform produces on its own; your work is the content
and the few settings only the owner can decide.
What Typeroll handles automatically
Section titled “What Typeroll handles automatically”Every publication produces these without any tool call. Do not recreate them
by hand, and do not add a second copy through json_ld, scripts_head or a
page.
Head of every page
<html lang>from the Pagelanguage, otherwise the sitelanguage.<title>:seo_title, otherwise the Page title, plusdefault_seo_suffixunless the Page setsappend_seo_suffix: false.<meta name="description">:seo_description, thendefault_meta_description, then the tagline.<link rel="canonical">: the resolved route on the publication’s origin, or an explicitcanonical_url.<meta name="robots">fromnoindexandnofollow, and from the site-wide and version restrictions.- Open Graph and Twitter card tags (
og:title,og:description,og:image,twitter:card,twitter:sitefromtwitter_handle). Sharing text usesog_titleandog_descriptionwhen set. - Share image chain:
og_image, then a public Content type field mapped toimage, thendefault_og_image, then the logo. An SVG, AVIF or TIFF share image from the site’s media library is published as a 1200×630 PNG copy, contained on the theme’s background colour; the original stays the page image.og:image:type,og:image:widthandog:image:heightare emitted. - hreflang
<link rel="alternate">for Pages withalternates. - A Markdown rendition of each indexable Page at
<page path>index.md, announced with<link rel="alternate" type="text/markdown">. - The first content images are never lazy and get
fetchpriority="high", and a first section’s background image is preloaded; later images are lazy. Logos and small icons do not count as the first images.
Structured data (JSON-LD)
OrganizationandWebSiteon the home page, fromsite_name,tagline,organization,logo, contact and social settings.Articlefor Pages withkind: "article", with dates andauthor.BreadcrumbListon every page below the home page, from resolved routes.- Content type schema from
schema_typeandschema_field_map. FAQPagefrom an Accordion block (core/accordion) when every item’s title ends with a question mark (?,?,؟) and has an answer. Nothing is added when the Page’sjson_ldor its Content type schema already declaresFAQPage, so it is never emitted twice.
Site files
robots.txt: yourrobots_txtsetting, with the sitemap lines added. Theai_crawler_policysetting adds the matching AI crawler groups. A duplicate load of a theme font in custom CSS orscripts_headis reported by the readiness itemduplicate_fonts, not removed.sitemap.xml: published, indexable Page routes. With more than 45,000 URLs it becomes a sitemap index over numberedsitemap-<n>.xmlfiles. Pages withalternatescarry their hreflang entries.sitemap-images.xml: the public images of each indexable Page.llms.txt: a Markdown map of the site for AI agents, grouped by Content type and language section, with each Page’s description and links to the sitemap andllms-full.txt.llms-full.txt: the Markdown of the indexable Pages in one file, with a size cap.- The
Content-Signalresponse header, whenai_crawler_policyis notallow_all.
Noindex and unlisted Pages, drafts and blocked versions are left out of every site file.
Recipe
Section titled “Recipe”1. Read the site’s state
Section titled “1. Read the site’s state”read_site_readinessread_site_settingslist_pages status="all"read_site_readiness returns items with id, status (ok,
suggestion or warning), message, fix and guide. Work through the
warnings first. It never blocks a publication, and a clean report is not
approval to publish.
For each important Page, check:
- Does the title identify the page, including any suffix?
- Is the description specific and supported by the page’s content? Search engines may rewrite or shorten snippets; never pad text to a length.
- Does the page have exactly one H1?
2. Launch basics only the owner can decide
Section titled “2. Launch basics only the owner can decide”Read read_site_settings first and ask only for what is missing. Each item is
optional; record a skipped item in decisions.md.
-
Default share image. Ask the user to choose or create the image shown when a page has none of its own: upload one (
create_upload_urlorupload_media_from_url), pick one withlist_media, or create one withtr-imagegen. Use 1200×630 px PNG or JPEG. Never generate a title card from the page title instead.update_site_settings default_og_image="<cdn_url>" twitter_handle="@acmestudio" -
Organization and profiles. The business name, logo and official profile URLs:
update_site_settings organization={"name":"Acme Studio","logo":"<cdn_url>","same_as":["https://www.linkedin.com/company/acme"]} -
Site description and icons.
default_meta_descriptionfor pages without their own description, andfavicon,apple_touch_iconandicon_192(seetr-brand). -
AI crawlers.
ai_crawler_policyisallow_all(the default, which writes nothing),no_trainingorblock_all:update_site_settings ai_crawler_policy="no_training"no_trainingdisallows training-only crawlers such as GPTBot, ClaudeBot, Google-Extended, Applebot-Extended and CCBot, and statesContent-Signal: search=yes, ai-input=yes, ai-train=no. It never blocks Googlebot, Bingbot or Applebot. On Cloudflare, the zone’s own AI bot policy is enforced at the edge and wins overrobots.txt; blocking Training there can also block Googlebot, Bingbot and Applebot. The readiness itemai_crawler_zone_conflictreports a mismatch. Never change the zone’s settings yourself: tell the owner what to change. -
Pages a business needs. Privacy policy, contact and a 404 page. Set the privacy page as
cookie_consent.privacy_policy_urlwhen the cookie banner is on.
3. Titles and descriptions
Section titled “3. Titles and descriptions”update_site_settings {"default_seo_suffix": " — Acme Studio", "trailing_slash": "always"}
batch_update_pages updates=[ {page_id: "home", patch: {seo_title: "Acme Studio — Interior design in Stockholm", seo_description: "Acme designs..."}}, {page_id: "about", patch: {seo_description: "We are..."}}]- Give the home page an explicit
seo_title, so the suffix does not repeat the site name. - A page that must keep its exact title can set
append_seo_suffix: false. - The readiness report flags duplicate titles and descriptions, missing or repeated H1s and descriptions over 160 characters. Fix them in the content; they are warnings, not rules to pad or trim text mechanically.
4. URLs and articles
Section titled “4. URLs and articles”- Slugs are lowercase kebab-case:
our-services, notOur_Services. - Reflect hierarchy in the address: a team member lives at
/team/jane-doe(setpath, or use a Content type whose route pattern adds the prefix). Breadcrumbs and their schema follow the resolved route. - Blog posts and news get
kind: "article"and anauthor. - Give shared pages, especially articles, their own
og_image. - Link every published page from somewhere. The readiness item
orphan_pageslists pages that no internal link reaches;check_internal_linksfinds broken saved links.
5. Structured data beyond the automatic output
Section titled “5. Structured data beyond the automatic output”Use structured data only for information the page visibly shows.
-
FAQ: an Accordion block whose item titles are questions ending in a question mark, each with an answer, produces
FAQPageautomatically. For FAQ content in another block, useadd_faq_schema. -
Recipes and events:
add_recipe_schemaandadd_event_schemavalidate the input, build the JSON-LD and merge it into the Page’sjson_ld:add_recipe_schema page_id="kanelbullar" name="Kanelbullar"ingredients=["500 g flour", "2 tsp cinnamon"] instructions=["Mix the dough.", "Bake at 225 °C."]prep_time="PT1H30M" cook_time="PT10M" recipe_yield="24 buns" image_url="<cdn_url>"add_event_schema page_id="summer-concert" name="Summer concert"start_date="2026-06-12T19:00:00+02:00" location_name="City Hall"location_address="Main Street 1, Sundsvall" offers_price=250 offers_currency="SEK"Read the returned
warnings: a recipe without an image or an event without a location is valid but not eligible for rich results. -
Products, software and directories: set the Content type’s
schema_type(for exampleProductorSoftwareApplication) and map its fields withschema_field_mapinupdate_content_type, rather than writing JSON-LD on each Page. -
Other types: write
json_ldyourself as a JSON string. Keep several nodes in one{"@context":"https://schema.org","@graph":[…]}. An update replaces the whole value, so read the Page first.update_page page_id="home" patch={"json_ld": "{\"@context\":\"https://schema.org\",\"@type\":\"LocalBusiness\",\"name\":\"Acme Studio\",\"url\":\"https://acme.se\"}"}
The readiness item structured_data reports JSON-LD that is missing required
properties or has invalid dates or URLs.
Instead of the schema_markup workflow. That workflow uses the
Organization’s own AI key; without it, it fails with
failure_code: "ai_not_enabled". Don’t retry it. Read each published page,
choose the one type it represents (or none), apply the tools above, and tell
the user you did it yourself.
6. robots.txt, indexing and canonicals
Section titled “6. robots.txt, indexing and canonicals”robots_txtholds custom crawl rules; the sitemap lines are added for you. Useai_crawler_policyfor AI crawlers instead of hand-written groups.- To keep a page out of search but crawlable, set
noindex: true. Blocking a path inrobots.txtstops crawlers from reading that directive. - Set
canonical_urlonly when a page deliberately points elsewhere, for example a cross-domain duplicate. Don’t combine it withnoindex. check_site_indexingreports the robots policy of the actual address, including response headers.
7. Languages
Section titled “7. Languages”update_site_settings {"language": "sv"}update_page page_id="about-en" patch={"language": "en"}For several languages on one site, use language_sections and Page
alternates; see the multilingual sites guide.
8. Search Console
Section titled “8. Search Console”Ask the owner to add the site in Google Search Console. A Domain property
verified with a DNS TXT record covers every address. For a URL-prefix
property, put Google’s verification <meta> tag in scripts_head (admin
permission). Then submit https://<host>/sitemap.xml. Record the property in
brief/seo.md. After launch, import_gsc_performance reads page clicks and
impressions into the URL inventory.
9. Publish and check
Section titled “9. Publish and check”With the user’s approval:
read_site_readinesstrigger_deployget_deploy_status job_id=<id>read_site_readinessRun the report again after the publication. It reads saved content and
settings: the AI crawler zone check needs the site’s website host, and a Search
Console property verified by DNS is not visible to Typeroll, so confirm it in
Search Console. Fix or record every open item, and save the result under the
starter’s qa/ folder. In the portal, the site’s overview page has the same
report under Launch readiness → Check readiness. It runs on request, not
after every publication.
Pitfalls
Section titled “Pitfalls”- Don’t stuff keywords. Write descriptions for people. Google ignores
<meta name="keywords">, and Typeroll has no such field. - JSON-LD is a string. Pass the whole schema as a JSON-encoded string in
json_ld. The server escapes</scriptbefore output. - Share images need absolute URLs. Media library
cdn_urlvalues are absolute. - FAQ markup must match visible content. Search engines penalize FAQ markup for questions the page does not show.
- A site file you write by hand loses. Don’t create Pages named
sitemap.xml,robots.txtorllms.txt; the publication writes them.