import type { OptionCopy } from '../../components/seo/option-row'; import type { ISeoGeneral, ISeoLocal, ISeoSitemap, } from '../../service/seo/seo.interface'; /** * What every SEO setting is called and what it does, laid out the way Rank * Math names its options: a label, the description under it, and a tip on * the info icon with the effect, the reason for the default or an example. */ export interface SectionCopy { title: string; description: string; } export const PAGES = { analytics: { title: 'Analytics', description: 'What Google Search Console knows about this site: the queries people typed, the pages that answered, clicks, impressions and positions, kept by Recomaze and refreshed every day.', }, checkup: { title: 'Checkup', description: 'Every check the plugin runs on the whole site, what it found, and the way to fix it: a button here, the Copilot, or a settings page. The Changes tab keeps what the automation wrote, with a way back for each change.', }, roles: { title: 'Role manager', description: 'Which roles may change the SEO settings, edit the SEO fields, spend AI credits, manage redirects and read the 404 log. Administrators always may.', }, local: { title: 'Local SEO', description: 'The business behind the site, for Google\u2019s local results: what kind of business, where it is, how to reach it and when it is open. Printed as LocalBusiness schema on every page and by the [recomaze_contact_info] shortcode.', }, links: { title: 'Links', description: 'Every link in your content, counted per post: what points in, what points out, which pages nothing links to, and which links are broken.', }, notFound: { title: '404 monitor', description: 'Every address visitors and crawlers asked for that does not exist, with how often and from where. Turn the ones that matter into redirects in one click.', }, redirects: { title: 'Redirects', description: 'Send old addresses to new ones so links and rankings survive a move. Slug changes on published posts make their own redirects; the 404 monitor shows what still needs one.', }, general: { title: 'General settings', description: 'How the site behaves beyond titles: links, breadcrumbs, redirects and the 404 log, image SEO, the look of the front-end pieces, webmaster codes, other SEO plugins, llms.txt, robots.txt and .htaccess, and the shop.', }, titles: { title: 'Titles & meta', description: 'How the title and description of every page are built, from the home page to each post type and taxonomy.', }, sitemap: { title: 'Sitemap', description: 'The XML sitemap: what goes in, what stays out, and how it is split.', }, } satisfies Record; export const SECTIONS = { links: { title: 'Links', description: 'Change how some links open and behave on the site. Applied when a page is printed; nothing here rewrites saved content.', }, breadcrumbs: { title: 'Breadcrumbs', description: 'The path to a page: Home, its section, the page. Show it with the Breadcrumbs block, the [recomaze_breadcrumb] shortcode or recomaze_breadcrumb() in a theme; Google reads it from the schema either way. The Breadcrumbs module on the dashboard turns all of it on and off.', }, redirects: { title: 'Redirects', description: 'How redirects behave: the type new ones get, whether slug changes make them by themselves, where unmatched 404s go, and a debug view for admins.', }, monitor404: { title: '404 monitor', description: 'What the log keeps and for how long. Static files never enter it; add your own exclusions for paths that are expected to 404.', }, images: { title: 'Image SEO', description: 'Alt and title attributes filled in from a format as pages are printed, captions for images without one, and tools for the media library. Formats take %filename%, %alt%, %title% (the post), %caption%, %description%, %seo_title%, %category% and the site variables such as %sitename% and %sep%. The Image SEO module on the dashboard turns the display-time part on and off.', }, woocommerce: { title: 'WooCommerce', description: 'What the shop adds to the head: the brand in the Product schema and the Open Graph tags, whether hidden products stay out of search, and the shop’s URLs without their bases.', }, frontend: { title: 'Front-end', description: 'The pieces the plugin puts on the site — the contact block, the store locator, breadcrumbs, the HTML sitemap and the FAQ, How-to and table of contents blocks — carry layout only and take the theme’s colours and type. See them as the theme prints them, and add your own CSS where the theme’s look is not enough.', }, webmaster: { title: 'Webmaster tools', description: 'Verification codes for Google, Bing and the other webmaster tools, printed as meta tags on the home page. Paste the code or the whole tag the tool gives you; only the code is kept.', }, plugins: { title: 'Other SEO plugins', description: 'Only one plugin may print the head of a page. While Rank Math, Yoast, AIOSEO or SEOPress is active, Recomaze prints no titles, descriptions, Open Graph or schema and keeps its sitemap off, so nothing is duplicated.', }, robots: { title: 'Edit robots.txt', description: 'What crawlers may and may not fetch. WordPress serves this file virtually; the editor fills it from here, or serves the default when empty.', }, htaccess: { title: 'Edit .htaccess', description: 'The Apache configuration at the root of the site: a backup before every save, and the site asked after it, with the previous file put back if it stops answering.', }, llms: { title: 'llms.txt', description: 'The Markdown index AI assistants and answer engines read at /llms.txt, and the llms-full.txt companion with the text of the newest entries. Both are built from the content on demand and cached for fifteen minutes.', }, others: { title: 'Others', description: 'Small output changes that fit nowhere else, and the text added around every item of the RSS feeds.', }, global: { title: 'Global meta', description: 'Defaults that apply across the whole site: the separator, capitalization, empty archives, the fallback social image and the Twitter card.', }, local: { title: 'Knowledge graph', description: 'Who this site belongs to and what it is called: the organization or person with its logo, the name Google shows for the site, and what the business does and how to reach it. Feeds the schema on every page, og:site_name and llms.txt. With an address under Local SEO, this organization becomes that LocalBusiness; the business card Google shows in Maps comes from your Google Business Profile.', }, social: { title: 'Social meta', description: 'Details the social networks read when a page of this site is shared.', }, homepage: { title: 'Homepage', description: 'The title and description of the front page in search results and the browser tab.', }, authors: { title: 'Authors', description: 'The author archives: their title, description and whether search engines list them.', }, misc: { title: 'Misc pages', description: 'Search results, the 404 page, date archives, and which paginated or protected pages stay out of search results.', }, sitemapGeneral: { title: 'General', description: 'A sitemap index at /sitemap_index.xml with one sitemap per post type, taxonomy and author, replacing the WordPress core sitemap. Submit the index once in Search Console; it updates itself on every publish.', }, sitemapMedia: { title: 'Videos & news', description: 'Two extra sitemaps: video-sitemap.xml lists the posts that embed a YouTube or Vimeo video or an uploaded one, for video results; news-sitemap.xml lists what was published in the last two days, for Google News.', }, sitemapHtml: { title: 'HTML sitemap', description: 'A page of links for readers. Put the [recomaze_html_sitemap] shortcode on any page; type="post,category" limits it to some sections.', }, sitemapIndexnow: { title: 'IndexNow', description: 'Tell Bing, Yandex, Naver, Seznam and Yep the moment a page is published, changed or removed, instead of waiting for their next crawl. Google does not take part. The IndexNow module on the dashboard turns it on; nothing is sent until the switch below is on too.', }, sitemapAuthors: { title: 'Authors', description: 'Author archives in the XML sitemap.', }, } satisfies Record; export const postTypeSection = (label: string): SectionCopy => ({ title: label, description: `Defaults for every one of the ${label.toLowerCase()}. What is written on one in the editor always wins over these.`, }); export const taxonomySection = (label: string): SectionCopy => ({ title: label, description: `Defaults for ${label.toLowerCase()} archives, the pages listing everything under one term. A term can override them from its edit screen.`, }); export const sitemapPostTypeSection = (label: string): SectionCopy => ({ title: label, description: `Whether ${label.toLowerCase()} are listed in the XML sitemap.`, }); export const sitemapTaxonomySection = (label: string): SectionCopy => ({ title: label, description: `Whether ${label.toLowerCase()} archives are listed in the XML sitemap.`, }); export const GENERAL: Record = { conflict_mode: { label: 'Editor fields meanwhile', description: 'What the SEO fields in the post editor do while another SEO plugin prints the head.', tip: 'Hidden: the fields disappear until the other plugin is deactivated, so nobody edits data that is not printed. Shown: the fields stay and save, so you can switch later without losing anything; the other plugin still owns the head.', }, remove_generator: { label: 'Remove generator tag', description: 'Drop the meta tag that announces your WordPress version.', tip: 'The tag helps nobody but people scanning for sites on an old version. Removing it changes nothing for search engines.', }, frontend_css: { label: 'Custom CSS', description: 'Your own rules for the plugin’s pieces, printed on every page after the theme’s stylesheets.', tip: 'The pieces use plain class names: .recomaze-contact, .recomaze-locator, .recomaze-breadcrumbs, .recomaze-html-sitemap, .recomaze-faq, .recomaze-howto, .recomaze-toc. Inspect the preview above to find the exact one. Markup is stripped; only CSS text is kept.', }, disable_xmlrpc: { label: 'Disable XML-RPC', description: 'Every method on xmlrpc.php answers with an error, pingbacks and system.multicall included, and the X-Pingback header and the RSD link go.', tip: 'XML-RPC is the old remote-publishing interface; today it mostly receives password-guessing floods. Nothing in Recomaze uses it; Jetpack and old publishing apps do, so leave it on if you use them. The Checkup turns this on for you under Security.', }, nofollow_external: { label: 'Nofollow external links', description: 'Add rel="nofollow" to every link in your content that points to another site.', tip: 'Tells search engines not to pass your authority to the linked site. Turn it on if you cannot vet every outbound link; leave it off if you link to sources on purpose.', }, links_check_external: { label: 'Check links to other sites', description: 'Once a week the link checker asks every site your pages link to whether the page still answers, and lists the ones that fail under Links → Broken.', tip: 'Off, only the links inside this site are checked and nothing is sent to other sites; broken outbound links then go unnoticed. The request names this site in its user agent.', }, new_window_external: { label: 'Open external links in a new tab', description: 'Add target="_blank" (with rel="noopener") to links pointing away from this site.', tip: 'Readers keep your page open when they follow a link out. Applied when the page is printed; the saved content does not change.', }, nofollow_domains: { label: 'Nofollow only these domains', description: 'One domain a line. Filled in, only links to these get nofollow; empty, every external link does.', tip: 'For a site that links out freely but wants nofollow on shops and affiliate partners only. A domain covers its subdomains: amazon.com covers smile.amazon.com.', }, nofollow_exclude_domains: { label: 'Never nofollow these domains', description: 'One domain a line: links to these stay followed, such as your other sites or sources you vouch for.', tip: 'For your own other sites and the sources you cite on purpose: a followed link passes on authority, which is right for a source you vouch for. A domain covers its subdomains.', }, nofollow_image_links: { label: 'Nofollow image file links', description: 'Add rel="nofollow" to images that link to their own file or attachment page.', tip: 'Those links lead to a bare image, nothing search engines should crawl; nofollow keeps them on your real pages.', }, strip_category_base: { label: 'Strip category base', description: 'Remove /category/ from category archive URLs: /news/ instead of /category/news/.', tip: 'Shorter URLs with the keyword closer to the domain. The old URLs redirect, but decide once: every category URL changes with it.', }, redirect_attachments: { label: 'Redirect attachments', description: 'Send the page WordPress creates for every uploaded file to the post it was uploaded to.', tip: 'Attachment pages are thin, near-empty pages that compete with your real content. Files uploaded outside a post are left alone.', }, robots_txt: { label: 'robots.txt', description: 'The content served at /robots.txt; empty means the WordPress default. Edited in its own section.', tip: 'The file crawlers read before anything else: which paths they may fetch and where the sitemap is. A wrong line can hide the whole site from search, so the editor flags lines crawlers do not know and groups that let a crawler past the rules for everyone, asks before a search engine is shut out and keeps the last five versions to restore; Back to the default file puts the one WordPress writes back.', }, rss_before: { label: 'RSS before content', description: 'Added at the top of every item in the feeds. Takes HTML, the usual variables, and %POSTLINK%, %AUTHORLINK%, %BLOGLINK%, %BLOGDESCLINK% and %FEATUREDIMAGE%.', tip: 'Feeds get copied by aggregators and scrapers. A line naming the site and linking back keeps the credit, and the link, wherever the item ends up.', }, rss_after: { label: 'RSS after content', description: 'Added at the end of every item, with the same variables. A common one: The post %POSTLINK% appeared first on %BLOGLINK%.', tip: 'The featured image is only in the feed if you put %FEATUREDIMAGE% here or above; WordPress does not add it by itself.', }, noindex_password_protected: { label: 'Noindex password-protected pages', description: 'Mark pages with a password as noindex.', tip: 'Search engines cannot see past the password anyway; noindex keeps the empty prompt page out of the results.', }, breadcrumbs_separator: { label: 'Separator', description: 'The character between two steps of the path.', tip: '» and › read as "leads to"; / mirrors the URL; — is quieter. One to five characters.', }, breadcrumbs_home_label: { label: 'Home label', description: 'What the first step, the link to the front page, is called.', tip: 'Home is what readers expect. A short brand name also works on shops.', }, breadcrumbs_prefix: { label: 'Prefix', description: 'Text printed before the path, such as "You are here:". Empty for none.', tip: 'Rarely needed; themes that show breadcrumbs under the header read fine without it.', }, breadcrumbs_show_home: { label: 'Show the home link', description: 'Start every path with the link to the front page.', tip: 'Off, the path starts at the section. Google still gets the full path from the schema.', }, breadcrumbs_hide_current: { label: 'Hide the current page', description: 'Leave the last step, the page itself, out of the path.', tip: 'Turn it on when the page title is printed right below the breadcrumbs and would repeat.', }, breadcrumbs_home_url: { label: 'Home link', description: 'Where the first step leads. Empty for the front page, or the front page of the page’s language on a multilingual site.', tip: 'A shop whose home page is only a banner can point it at /shop/. A path starting with / stays on this site; the schema gets the full address.', }, breadcrumbs_archive_format: { label: 'Archive format', description: 'The step of an author or date archive. %s is the author’s name or the date.', tip: '%s alone prints just the name, as now; "Archives for %s" reads "Archives for Jane Doe". Without %s, the name follows the text.', }, breadcrumbs_search_format: { label: 'Search results format', description: 'The step of a search results page. %s is what was searched for.', tip: 'Without %s, the search follows the text: "You searched for" reads "You searched for hoodies".', }, breadcrumbs_404_label: { label: '404 label', description: 'The step of a page that does not exist.', tip: 'It shows only in the visible path; a missing page has no breadcrumb schema.', }, breadcrumbs_parent_terms: { label: 'Show parent categories', description: 'On a post or product, show the categories above its category: Home › Clothing › Hoodies › the product.', tip: 'Off, only the category the item is filed under shows (its primary one, when set). Category pages always show where they sit.', }, breadcrumbs_blog_page: { label: 'Show the posts page', description: 'With a static front page, put the posts page (Blog, Journal) before the category of a post and on category and tag pages.', tip: 'Off, a post reads Home › Category › Post. The posts page itself always shows as its own step.', }, redirects_default_code: { label: 'Default redirect type', description: 'What a new redirect is set to before you change it.', tip: '301 for anything that moved for good. 302 or 307 only for a page that comes back.', }, redirects_auto_post: { label: 'Redirect changed slugs', description: 'When a published post, page or product changes its slug or parent, redirect the old address to the new one.', tip: 'Keeps every inbound link and ranking alive without anyone remembering to add the redirect. Shown in the Redirects list like any other.', }, redirects_pass_query: { label: 'Keep the query string', description: 'Add what came after the ? in the old address (utm_source, gclid, fbclid…) to the new one.', tip: 'Without it a campaign link that lands on a redirected page loses its tracking, and the visit counts as direct in Analytics and the ad platforms. A parameter the destination sets itself keeps its value.', }, redirects_debug: { label: 'Debug redirects', description: 'Show administrators a page that says where a redirect leads instead of redirecting them.', tip: 'Useful while setting redirects up: you see which rule matched. Visitors are always sent straight on.', }, redirects_fallback: { label: 'Unmatched 404 pages', description: 'Where a 404 goes when no redirect matches it.', tip: 'The default 404 page is the honest answer and what Google expects; send everything to the homepage only on a site with a lot of dead links.', }, redirects_fallback_url: { label: 'Custom fallback URL', description: 'The page 404s go to, on this site or another. Visitors are sent there with a 302.', tip: 'A page that helps a lost visitor (search, categories, bestsellers) keeps more of them than the homepage does. Google still treats a mass redirect of dead pages as soft 404s.', }, monitor_404_mode: { label: 'Log mode', description: 'Simple keeps one row per address with a visit count; advanced keeps every visit with its referer and browser.', tip: 'Simple is enough to find broken links. Advanced tells you where each visit came from, at the cost of a bigger log.', }, monitor_404_ignore_query: { label: 'Ignore query parameters', description: 'Log /old-page?utm_source=news and /old-page?gclid=… as one address, /old-page.', tip: 'Campaign and tracking parameters otherwise make a new row per click and push the real broken links out of the capped log. Off keeps the full address, for sites whose pages differ by parameter.', }, monitor_404_exclude: { label: 'Exclude paths', description: 'One per line. A fragment matches anywhere in the address; a line starting with ^ or wrapped in /slashes/ is a regular expression.', tip: 'Use it for probes you cannot stop, such as /wp-login.php guesses or /.env, so the log shows real broken links.', }, monitor_404_limit: { label: 'Rows kept', description: 'The newest rows kept when the daily clean-up runs; 0 keeps them all.', tip: 'The log keeps what is worth acting on; one-off typos pile up otherwise. 0 keeps every row, which on a busy site grows the database.', }, monitor_404_purge_days: { label: 'Days kept', description: 'Rows older than this are dropped by the daily clean-up; 0 keeps them forever.', tip: 'An address nobody asked for again in a month is rarely worth a redirect. 0 keeps the rows forever.', }, image_alt_missing: { label: 'Add missing alt attributes', description: 'Images printed without alt text get one from the format below.', tip: 'Alt text is what Google Images and screen readers read. The filename is the honest default; write real alt text in the media library for images that matter.', }, image_alt_format: { label: 'Alt format', description: 'How the alt is built; %filename% turns zipper_hoodie-front.jpg into "Zipper hoodie front".', tip: 'Alt text is what screen readers say and what search engines understand an image by. The format fills the images that have none, and every image only when the replace switch below is on.', }, image_alt_change_all: { label: 'Replace existing alt attributes', description: 'Apply the alt format to every image, not just the ones without alt text.', tip: 'Only for sites whose alt texts are junk across the board. It hides the alt texts authors wrote.', }, image_title_missing: { label: 'Add missing title attributes', description: 'Images printed without a title attribute get one from the format below.', tip: 'The title shows as a tooltip; it matters little for ranking and mostly helps people. Off by default.', }, image_title_format: { label: 'Title format', description: 'How the title attribute is built.', tip: 'The title attribute shows as a tooltip on hover and weighs little in search. It fills images that have none, unless the switch below replaces them all.', }, image_title_change_all: { label: 'Replace existing title attributes', description: 'Apply the title format to every image.', tip: 'Replaces the title attributes you set with the format above, on every page. Worth it only when the existing ones are file names.', }, image_caption_missing: { label: 'Add missing captions', description: 'Image blocks printed without a caption get a figcaption from the format below.', tip: 'Only images in the block editor\u2019s image block. With %caption% as the format, the media library caption shows up under the image.', }, image_caption_format: { label: 'Caption format', description: 'How the caption is built; empty results add nothing.', tip: 'A caption is read by visitors and by search engines as text about the picture. The format fills only images without one.', }, image_alt_on_upload: { label: 'Set alt text on upload', description: 'Uploads that arrive without alt text get one from the alt format, saved in the media library.', tip: 'Unlike the options above, this writes to the database, once, when the file is uploaded.', }, image_alt_ai_on_upload: { label: 'Write alt text with AI on upload', description: 'An upload the format left without alt text is sent to Recomaze, which looks at the picture and describes it.', tip: 'Two credits per image, at upload time. The alt text is journaled in SEO \u2192 Checkup \u2192 Changes, so it can be put back.', }, wc_brand_taxonomy: { label: 'Brand taxonomy', description: 'Where the brand of a product is read from when the Product tab of its SEO box leaves it empty.', tip: 'Brand taxonomies (WooCommerce Brands, a brands plugin) are listed first, then the product attributes, marked as such; shops that keep the brand as an attribute pick that one. The brand goes into the Product schema and the product:brand tag.', }, wc_noindex_hidden: { label: 'Noindex hidden products', description: 'Products with catalog visibility set to Hidden get a noindex tag and stay out of the sitemap and llms.txt. On by default.', tip: 'Hidden products are for direct links and bundles; a noindex keeps Google from listing a page the shop itself does not show. "Shop only" and "Search results only" products are not hidden and stay indexed.', }, wc_remove_product_base: { label: 'Remove the product base', description: 'Product URLs without the /product/ part: /blue-hoodie/ instead of /product/blue-hoodie/. The old addresses redirect.', tip: 'Shorter URLs with the product name right after the domain. A product whose slug matches a page keeps the page in front; the slug is looked up on every request that reaches a top-level address, one indexed query. Decide once: every product URL changes with it.', }, wc_remove_category_base: { label: 'Remove the category base', description: 'Product category URLs without the /product-category/ part: /hoodies/ instead of /product-category/hoodies/. The old addresses redirect.', tip: 'The category name lands right after the domain, as with the blog categories above. Every category URL changes with it, so decide once.', }, wc_remove_parent_slugs: { label: 'Remove parent slugs', description: 'A child category keeps only its own slug: /product-category/hoodies/ instead of /product-category/clothing/hoodies/.', tip: 'Shorter addresses for deep category trees. Child slugs must then be unique across the shop, which WooCommerce already requires.', }, wc_return_policy: { label: 'Return policy', description: 'How returns work at this shop, printed once on the Organization and pointed to by every offer.', tip: 'Google shows the return window in shopping results, and Search Console warns on every product without one. Say what the shop actually offers; it is a promise.', }, wc_return_days: { label: 'Days to return', description: 'How many days after delivery a customer may send it back.', tip: 'Printed as merchantReturnDays in the return policy of the Organization schema; Google shows the policy with the product in results and merchant listings.', }, wc_return_fees: { label: 'Return shipping', description: 'Who pays for sending a product back.', tip: "Free returns show as such in Google's product results, a strong reason to click. Printed as returnFees.", }, wc_return_method: { label: 'How products come back', description: 'Where customers hand in a return.', tip: 'Printed as returnMethod on the return policy Google shows with the product.', }, wc_return_countries: { label: 'Return countries', description: 'The countries the policy applies to, as two-letter codes: US, CA. Empty, the shop’s own country.', tip: 'Google applies a return policy per country: list every country this policy covers. Printed as applicableCountry.', }, wc_shipping_details: { label: 'Shipping in the schema', description: 'Each offer states its shipping cost and delivery time, from the fields below.', tip: 'One flat rate for the whole shop, free from the threshold up. Zones with several rates or weight-based costs are not described; leave this off then rather than state a wrong cost.', }, wc_shipping_rate: { label: 'Shipping cost', description: 'The flat rate, in the shop’s currency. 0 for free shipping.', tip: 'Printed as the shipping rate of every offer. Google shows it beside the price, and Merchant Center marks listings without shipping as incomplete.', }, wc_shipping_free_over: { label: 'Free shipping from', description: 'Orders at this price or above ship free; each offer says free or the flat rate by its own price. Empty for no threshold.', tip: 'Each product says free shipping once its own price reaches this amount, as the shop charges it.', }, wc_shipping_countries: { label: 'Shipping countries', description: 'Where the shop ships, as two-letter codes: US, CA. Empty, the shop’s own country.', tip: "Where the rate above applies. Google shows the offer's shipping to shoppers in these countries.", }, wc_handling_days: { label: 'Handling days', description: 'Business days before a parcel leaves: 0-1 means the same or the next day.', tip: 'With the transit days, Google shows a delivery estimate ("Get it by Friday") next to the product.', }, wc_transit_days: { label: 'Transit days', description: 'Days the carrier needs to deliver: 2-5.', tip: 'Added to the handling days for the delivery estimate Google shows with the product.', }, breadcrumbs_woocommerce: { label: 'Replace the WooCommerce breadcrumbs', description: 'Print this path where WooCommerce prints its own on shop, category and product pages. Off, the shop keeps WooCommerce’s path and the schema describes that one.', tip: 'Classic themes get this path in place of WooCommerce’s; block themes keep WooCommerce’s Breadcrumbs block, which then shows this path. Either way the visible path and the one in the schema match: off, the BreadcrumbList on shop pages is WooCommerce’s own (no Shop step unless WooCommerce shows one).', }, }; export const TITLES: Record = { separator: { label: 'Separator character', description: 'The character between the parts of a title, printed wherever a template uses %sep%.', tip: 'Example: Blue running shoes | My Store. Pick one that reads well; a short one leaves more room for words.', }, capitalize_titles: { label: 'Capitalize titles', description: 'Start every word of the printed title with a capital letter. Words with a capital inside (iPhone, eBay) stay as written, and on an English site so do short words such as a, of and the.', tip: 'Applies to what search engines and the browser tab see, not to the titles saved on your posts.', }, noindex_empty_archives: { label: 'Noindex empty category and tag archives', description: 'Mark archives with no posts as noindex.', tip: 'An empty category or tag page has nothing to rank and thins out the site in Google’s eyes; on by default.', }, robots_max_snippet: { label: 'Max snippet', description: 'How many characters of an indexed page Google may show, -1 for no limit. Empty prints nothing.', tip: 'This is also what AI Overviews and the other answer features may quote: a limit shortens what gets cited. -1 is Rank Math’s default too.', }, robots_max_video_preview: { label: 'Max video preview', description: 'How many seconds of a video Google may play as a preview, -1 for no limit.', tip: '-1 lets Google show as much as it wants, 0 a still frame only. Applies to every indexed page with a video; a page can set its own.', }, robots_max_image_preview: { label: 'Max image preview', description: 'How large an image Google may show from an indexed page. Large lets it appear in Discover and in image-rich results.', tip: 'Large is needed for Google Discover and the large image results; Standard or None keeps pictures small or out. A page can set its own.', }, og_default_image: { label: 'Default social image', description: 'Shown when a shared page has no image of its own. A full URL.', tip: 'At least 1200 × 630 pixels; Facebook, LinkedIn and X all read it.', }, twitter_card_type: { label: 'Twitter card type', description: 'How links to this site look on X (Twitter).', tip: 'Summary with large image shows the image full width; Summary shows a small thumbnail beside the text.', }, knowledge_graph_type: { label: 'Person or organization', description: 'Whether Google should understand the site as an organization or a person.', tip: 'Pick person for a personal blog or portfolio; organization for a company, shop or publication.', }, knowledge_graph_name: { label: 'Name', description: 'Your name or the company name, as it should appear in the knowledge panel.', tip: 'With Local SEO on and an address set, the organization is printed as a LocalBusiness, and a business name set there wins. A person has no Local SEO output.', }, knowledge_graph_logo: { label: 'Logo', description: 'The logo used in the knowledge panel and in article rich results. A full URL.', tip: 'Square, at least 112 × 112 pixels, on a URL Google can fetch.', }, website_name: { label: 'Website name', description: 'The name Google shows for the site in results, above the address. Also og:site_name on shared links, the name in the snippet preview and the heading of llms.txt.', tip: 'Leave it empty to use the organization name, or the site title. Google reads it from the WebSite schema of the home page; use the name people call the site, consistently.', }, website_alternate_name: { label: 'Alternate name', description: 'Another name the site is known by, such as an acronym or a shorter form. Google may show it when it cannot use the main one.', tip: 'Printed as alternateName on the WebSite schema: Google uses it for the site name in results when the main one does not fit or is taken.', }, organization_description: { label: 'What the organization does', description: 'One or two sentences on what the business is and sells. Printed as the description of the Organization schema, and the summary of llms.txt when it has none of its own.', tip: 'AI assistants and the knowledge panel answer “what is this company” from it. Write it the way a customer would say it: “Cast Iron Corner sells restored cast-iron cookware and ships across Europe.”', }, organization_legal_name: { label: 'Legal name', description: 'The registered name, when it differs from the brand: “Cast Iron Corner SRL”. Printed as legalName.', tip: 'For the knowledge panel and the AI answers that tell the brand and the company apart; printed only when filled in.', }, organization_founding_date: { label: 'Founded', description: 'The year the business was founded, or the full date: 2014 or 2014-05-01. Printed as foundingDate.', tip: 'Among the business facts AI assistants quote about a company; printed only when filled in.', }, organization_email: { label: 'Contact email', description: 'Where customers can write. Printed on the Organization schema and in llms.txt.', tip: 'Local SEO’s own email wins when the Local SEO module is on and has one.', }, organization_phone: { label: 'Contact phone', description: 'With the country code: +40 721 000 000. Printed on the Organization schema and in llms.txt.', tip: 'Local SEO’s own phone wins when the Local SEO module is on and has one.', }, facebook_app_id: { label: 'Facebook app ID', description: 'Printed as fb:app_id so Facebook can attribute shares to your app.', tip: 'Only needed if you use Facebook analytics on shared links. Leave it empty otherwise.', }, home_title: { label: 'Homepage title', description: 'The title tag of the front page.', tip: 'Keep it under 60 characters so Google does not cut it off; put what the site is about before the site name.', }, home_description: { label: 'Homepage meta description', description: 'The snippet under the home page in search results.', tip: 'Up to 155 characters. Google may replace it, but a clear one raises the click rate.', }, author_title: { label: 'Author archive title', description: 'Title tag of the page listing an author’s posts; %author% is the display name.', tip: 'Author archives are often thin copies of the blog: title them distinctly, or set them to noindex under Authors.', }, author_description: { label: 'Author archive description', description: 'Snippet of the author page. Empty means none is printed.', tip: "Search engines show it under the author page's title; %author% and %sitename% work here too.", }, author_noindex: { label: 'Noindex author archives', description: 'Keep author pages out of search results.', tip: 'Recommended on a single-author site, where the author page repeats the blog. Keep them indexable when several people write.', }, date_noindex: { label: 'Noindex date archives', description: 'Keep the year and month archives out of search results.', tip: 'Date archives rarely rank and repeat the blog; on by default.', }, date_archive_title: { label: 'Date archive title', description: 'Title tag of the year, month and day archives; %date% is the period shown: 2026, September 2026.', tip: "Date archives list the blog's posts again by period; most sites keep them out of search. The title still names the period.", }, date_archive_description: { label: 'Date archive description', description: 'Meta description of the date archives. Empty prints none.', tip: 'Rarely needed: date archives are usually kept out of search.', }, search_title: { label: 'Search results title', description: 'Title tag of the site search results page; %search_query% is what was searched.', tip: 'Search result pages are kept out of search; this title shows in the browser tab and when the page is shared.', }, search_noindex: { label: 'Noindex search results', description: 'Keep the site search pages out of search engines.', tip: 'Search result pages are endless and repeat your content. Google asks for them to be noindexed; on by default.', }, not_found_title: { label: '404 title', description: 'Title tag of the page shown when nothing is found at a URL.', tip: 'Shown in the browser tab when an address does not exist; search engines do not index 404 pages.', }, noindex_paginated: { label: 'Noindex paginated pages', description: 'Mark page 2, 3 and so on of any archive as noindex.', tip: 'Fewer thin pages in the index; page 1 still ranks. Off by default, Google handles pagination well on its own.', }, noindex_paginated_single: { label: 'Noindex paginated posts', description: 'Mark page 2, 3 and so on of a post or page split with a page break as noindex.', tip: 'A long guide split into pages is found through its first page. Turn it on when the later pages read as fragments; the first page and its canonical stay as they are.', }, }; export const TITLES_MORE: Record = { author_archives: { label: 'Author archives', description: 'Whether the author pages exist. Off sends them to the front page with a 301.', tip: 'A one-author site gains nothing from author archives: they repeat the blog listing. Keep them on multi-author sites and noindex them if they thin the site out.', }, author_base: { label: 'Author base', description: 'The part of author archive URLs that stands for "author": /author/name/ by default.', tip: 'Change it to writer or team when that reads better. Permalinks are rebuilt when it is saved.', }, author_add_meta_box: { label: 'Add SEO controls', description: 'Show the Recomaze SEO box on user profiles, for the title, description and robots of an author archive.', tip: 'Useful when authors have an archive worth ranking, such as a named expert; off, author archives follow the templates.', }, date_archives: { label: 'Date archives', description: 'Whether the year, month and day pages exist. Off sends them to the front page with a 301.', tip: 'Date archives rarely rank and duplicate the blog listing; most sites turn them off.', }, home_og_title: { label: 'Social title', description: 'The title of the front page in share cards; the homepage title above when empty.', tip: 'What Facebook, LinkedIn, WhatsApp and X show when the home page is shared. Written for people scrolling, it can differ from the search title.', }, home_og_description: { label: 'Social description', description: 'What the front page says in a share card.', tip: 'One or two sentences under the title of the share card; the homepage description when empty.', }, home_og_image: { label: 'Social image', description: 'The image of the front page in share cards. A full URL, at least 1200 × 630 pixels.', tip: 'The picture of the share card: 1200 × 630 pixels shows sharp everywhere. Without one, platforms pick a picture from the page, often the logo.', }, social_facebook_url: { label: 'Facebook page', description: 'The full URL of the Facebook page: printed as article:publisher on articles and added to the sameAs of the Organization schema.', tip: "Links the site's articles to the page and tells Google which profiles belong to the business (sameAs), for the knowledge panel.", }, social_twitter: { label: 'X (Twitter) username', description: 'The username; a pasted profile address or an @ is cut down to it. Printed as twitter:site, so X credits the account on shared links, and added to sameAs.', tip: 'Credits the account when a link is shared on X and ties the profile to the business in the schema.', }, social_profiles: { label: 'Additional profiles', description: 'Other profiles of the business, one URL per line: Instagram, LinkedIn, YouTube, Pinterest. They join sameAs in the Organization or Person schema; https:// is added when missing.', tip: 'sameAs tells Google which profiles belong to the same entity as the site, which feeds the knowledge panel.', }, }; export const WEBMASTER_TIP = 'Copy the content attribute of the meta tag the service gives you. The tag is printed on the home page; once verified, the code can stay.'; /** Rows of the WooCommerce section that act instead of storing a setting. */ export const WOOCOMMERCE_TOOLS: Record<'shipping_fill', OptionCopy> = { shipping_fill: { label: 'Fill from WooCommerce', description: 'Reads the shop’s shipping zones and fills the fields below with what they charge. Nothing is saved until you save.', tip: 'Only what maps exactly: zones of whole countries whose methods are a fixed flat rate and free shipping from an order total, when they agree. Formulas, shipping-class costs, pickups, rate plugins, zones by state or postcode and zones with another rate are named with the reason and left to you.', }, }; export const WEBMASTER_LABELS: Record = { custom: { label: 'Other verification tags', description: 'The tag any other service gives you, one a line: Facebook, Ahrefs, Seznam, Naver and the like. Printed on the home page.', tip: 'Only the name and the content of each tag are kept, so nothing else reaches the page head. Ten tags at most.', }, google: { label: 'Google Search Console', description: 'The verification code from the HTML tag method.', tip: WEBMASTER_TIP, }, bing: { label: 'Bing Webmaster Tools', description: 'The verification code from the meta tag option.', tip: WEBMASTER_TIP, }, yandex: { label: 'Yandex Webmaster', description: 'The verification ID from the meta tag method.', tip: WEBMASTER_TIP, }, pinterest: { label: 'Pinterest', description: 'The code from claiming the website in Pinterest.', tip: WEBMASTER_TIP, }, baidu: { label: 'Baidu Webmaster Tools', description: 'The verification code from the HTML tag method.', tip: WEBMASTER_TIP, }, norton: { label: 'Norton Safe Web', description: 'The site verification ID.', tip: WEBMASTER_TIP, }, }; export const postTypeFields = ( label: string ): Record< | 'title' | 'description' | 'archive_title' | 'archive_description' | 'archive_noindex' | 'noindex' | 'schema' | 'og_image' | 'og_overlay' | 'add_meta_box' | 'bulk_editing' | 'analyze_fields' | 'primary_taxonomy', OptionCopy > => { const plural = label.toLowerCase(); return { og_image: { label: 'Social image', description: `Share image for ${plural} without an image of their own, before the site-wide default. A full URL.`, tip: 'Without it, shared pages of this type use the site-wide share image, or none.', }, og_overlay: { label: 'Badge on the social image', description: `Drawn in the middle of the image shared for ${plural}: a play button for video, a GIF label for animations.`, tip: 'The badge is drawn once, on a copy kept next to the uploads; the original image is never touched. A page can choose its own in the editor. Needs GD or Imagick on the server.', }, add_meta_box: { label: 'Add SEO controls', description: `Show the Recomaze SEO panel when editing ${plural}.`, tip: 'Off hides the panel in the block editor and the classic box; the SEO fields already saved stay and keep printing.', }, bulk_editing: { label: 'Bulk editing', description: `What the ${plural} list offers: the SEO column with Quick Edit and Bulk Edit, the column alone, or nothing.`, tip: 'Editing titles and descriptions from the list is the quickest way through many pages; turn it off for types whose SEO is set elsewhere.', }, analyze_fields: { label: 'Custom fields', description: 'Meta keys whose values count as content in the SEO analysis, one per line.', tip: 'For content kept in custom fields (ACF, page builders): the keyword, length and readability tests then see it too.', }, primary_taxonomy: { label: 'Primary taxonomy', description: `Where the primary term of ${plural} comes from, for the breadcrumb trail and the article section.`, tip: 'Only matters for post types filed under more than one hierarchical taxonomy.', }, schema: { label: 'Schema type', description: `What one of the ${plural} is, in the JSON-LD graph, unless the editor says otherwise.`, tip: 'Blog post for posts, Article for most other content, News article only for a newsroom. Service, Course and Person are named and described by each page itself. Recipe, Event, Job posting, Video, Software and Book need details only the author knows, so they print once a page has them: its Schema tab offers to add them. None prints just the WebPage; products always get Product.', }, title: { label: 'Title', description: `Default title tag for ${plural}. The SEO title written on one in the editor overrides it.`, tip: 'Keep %title% first so the keyword is at the front, and the site name last.', }, description: { label: 'Description', description: `Default meta description for ${plural}. %excerpt% takes the excerpt, or the first sentences of the content.`, tip: 'This is only the fallback so nothing goes out empty; write the real one per item in the editor.', }, archive_title: { label: 'Archive title', description: `Title tag of the ${plural} archive, the page listing all of them.`, tip: 'For products this is the shop page: an SEO title written on that page in the editor wins over this template.', }, archive_description: { label: 'Archive description', description: `Meta description of the ${plural} archive. Empty, the archive prints none and Google picks a snippet.`, tip: 'For products this is the shop page: a description written on that page in the editor wins over this one.', }, archive_noindex: { label: 'Noindex the archive', description: `Keep the ${plural} archive out of search results, whatever the ${plural} themselves do.`, tip: 'Separate from the switch for the single items, so noindexing the items never takes the listing page with them. The shop page can also be set to noindex in its own editor.', }, noindex: { label: 'Noindex', description: `Keep every one of the ${plural} out of search results.`, tip: 'The pages stay online and linkable, they just do not rank. Use it for internal content; attachments default to on.', }, }; }; export const taxonomyFields = ( label: string ): Record< 'title' | 'description' | 'noindex' | 'add_meta_box' | 'remove_schema', OptionCopy > => { const plural = label.toLowerCase(); return { add_meta_box: { label: 'Add SEO controls', description: `Show the Recomaze SEO box when editing ${plural}.`, tip: "Off, these keep the templates and nobody sets a page's own SEO fields: for types that never show in search.", }, remove_schema: { label: 'Remove schema data', description: `Print no JSON-LD on ${plural} archives.`, tip: 'For archives that should not qualify for rich results, or when something else prints their schema.', }, title: { label: 'Archive title', description: `Title tag of every ${plural} archive; %term% is the term name.`, tip: "Every term of this taxonomy gets this title unless it has its own; %term% keeps each archive's title distinct.", }, description: { label: 'Archive description', description: `Meta description of a ${plural} archive. %term_description% takes the description saved on the term, nothing when it has none.`, tip: 'The snippet of each archive: write a description on the term itself to feed %term_description%.', }, noindex: { label: 'Noindex', description: `Keep ${plural} archives out of search results.`, tip: 'Tag archives start noindexed: they repeat post content and rarely rank. Category archives usually stay indexable.', }, }; }; export const SITEMAP: Record = { enabled: { label: 'Generate the sitemap', description: 'Serve /sitemap_index.xml and disable the WordPress core sitemap.', tip: 'Off, WordPress keeps serving its own /wp-sitemap.xml, without images, exclusions or the extra sitemaps.', }, links_per_sitemap: { label: 'Links per sitemap', description: 'How many URLs one sitemap file holds before it is split into another; 10 to 2000.', tip: 'Smaller files are fetched faster; 200 suits most sites.', }, include_images: { label: 'Images in sitemaps', description: 'List the images of every post inside its sitemap entry.', tip: 'Helps images rank in Google Images; makes each sitemap larger.', }, include_authors: { label: 'Include in sitemap', description: 'Add a sitemap of author pages.', tip: 'Only useful when author archives are indexable and several people write.', }, ping_indexnow: { label: 'Notify IndexNow on publish', description: 'Tell Bing, Yandex and the other IndexNow engines each time a page is published, updated or deleted.', tip: 'Instant instead of waiting to be crawled. Bing feeds Copilot and ChatGPT search, so a change reaches them sooner too. Google does not use IndexNow. On by default: switching the IndexNow module on is enough.', }, exclude_posts: { label: 'Exclude posts', description: 'Posts, pages or products to leave out: search for them and pick. Applies to every post type.', tip: 'A single page can also be excluded from its editor sidebar.', }, exclude_terms: { label: 'Exclude terms', description: 'Categories, tags or other terms to leave out: search for them and pick. Applies to every taxonomy.', tip: 'The archives of these terms leave the sitemap, for tags or categories not worth ranking; their posts stay listed.', }, include_empty_terms: { label: 'Include empty terms', description: 'List archive pages of terms that have no content yet. Applies to every taxonomy.', tip: 'An empty archive is a thin page; most sites leave these out until the term has something to show.', }, post_types: { label: 'Include in sitemap', description: 'List this post type in the XML sitemap.', tip: 'A post type marked noindex under Titles & meta is left out anyway.', }, taxonomies: { label: 'Include in sitemap', description: 'List the archive pages of this taxonomy in the XML sitemap.', tip: 'Include archives with real content, such as product and main categories; tags with a post or two read as thin pages.', }, include_videos: { label: 'Video sitemap', description: 'Serve video-sitemap.xml with the videos found in the content of the listed post types.', tip: 'YouTube and Vimeo embeds and uploaded video files are found when a post is saved; existing posts are read once in the background.', }, news_enabled: { label: 'News sitemap', description: 'Serve news-sitemap.xml with the articles of the last 48 hours, the way Google News wants them.', tip: 'Only useful for sites accepted in Google News Publisher Center. Submit the file there once.', }, news_publication_name: { label: 'Publication name', description: 'The name registered in Publisher Center. Empty, the website name of Titles & meta is used, else the name of the organization.', tip: 'Google News matches it with your Publisher Center entry; a different name can keep articles out of News.', }, news_post_types: { label: 'News post types', description: 'Which post types count as news.', tip: 'Only articles published in the last two days go into the news sitemap, as Google News asks.', }, html_sitemap_sort: { label: 'Sort posts by', description: 'The order of the posts inside each section of the HTML sitemap.', tip: 'Published or modified first suits a blog; alphabetical suits a shop or a reference site.', }, html_sitemap_dates: { label: 'Show dates', description: 'Print the publish date after each post.', tip: 'Dates help the readers of a blog; on evergreen pages they make the content look old.', }, html_sitemap_seo_titles: { label: 'Use SEO titles', description: 'Link with the SEO title instead of the post title, without the separator and the site name.', tip: 'Worth it when the SEO titles say more than the post titles (Zipper hoodie for winter rather than Zipper hoodie).', }, }; export const LOCAL_SECTIONS = { locations: { title: 'Locations', description: 'Several branches of the same business. Each becomes a page with its own address, hours and map, a LocalBusiness entry under the organization, a pin in locations.kml and an entry in the store locator. The head office above leads both lists; the location pages join the XML sitemap, and local-sitemap.xml tells search engines where the KML file is.', }, business: { title: 'Business', description: 'Who and where. With an address, the Organization of Titles & meta → Knowledge graph becomes this LocalBusiness on every page: its name, type, address, phone and hours. What Maps and the local pack show comes from your Google Business Profile; keep the two the same.', }, contact: { title: 'Contact & hours', description: 'How customers reach you and when the doors are open. The hours go into the schema and the contact block.', }, pages: { title: 'Pages & map', description: 'Which pages are the About and Contact pages, so their schema says so, and whether the contact block shows a map.', }, }; /** The address box is not a setting of its own: it fills the ones under it. */ export const LOCAL: Record = { multiple_locations: { label: 'Several locations', description: 'Adds a Locations menu to WordPress for the branches, the /locations/ pages and the [recomaze_store_locator] shortcode.', tip: 'The business above stays the head office and the organization in the schema; each branch points at it as its parent. Turn it off and the location pages disappear, their data stays.', }, business_type: { label: 'Business type', description: 'The schema.org kind closest to what you do.', tip: 'Pick the most specific one that fits; LocalBusiness is the generic fallback. It tells search engines and assistants what kind of place this is; the category Google shows comes from your Google Business Profile.', }, name: { label: 'Business name', description: 'As it should appear in Google. Empty, the knowledge graph name is used.', tip: 'Google compares it with the name on your Google Business Profile: keep the two the same.', }, address_search: { label: 'Find your address', description: 'Write the address the way you would say it and pick yours; the fields below fill themselves.', tip: 'The lookup runs on your site, not in the browser, because OpenStreetMap asks to know which application is calling and refuses a request per keystroke. With a Google Maps key in the section below, Google answers instead. Answers are kept for a day, so the same address costs one request.', }, street: { label: 'Street address', description: 'Street and number. Local SEO turns on once this is filled in.', tip: 'Printed in the LocalBusiness schema and the contact block; match your Google Business Profile exactly.', }, locality: { label: 'City', description: 'City or town.', tip: 'Part of the address in the schema; with the postal code and the country it places the business on the map.', }, region: { label: 'Region', description: 'County, state or province, as an abbreviation or in full.', tip: 'Part of the address in the schema; it tells apart towns of the same name.', }, postal_code: { label: 'Postal code', description: 'As the post office writes it.', tip: 'Part of the address in the schema; match your Google Business Profile.', }, country: { label: 'Country', description: 'The two-letter code, such as RO or DE, or the full name.', tip: 'The two-letter code is what the schema expects and what Google reads most reliably; a full name is printed as typed.', }, phone: { label: 'Phone', description: 'With the country code; printed as a tap-to-call link.', tip: 'Printed in the schema and the contact block; the same number as on your Google Business Profile helps Google trust the listing.', }, email: { label: 'Email', description: 'Printed as a mailto link.' }, price_range: { label: 'Price range', description: 'Dollar signs from $ to $$$$, or a short range such as 10-50 EUR. Up to 30 characters.', tip: 'Printed as priceRange on the LocalBusiness schema. What Google shows in Maps and the local pack comes from your Google Business Profile.', }, latitude: { label: 'Latitude', description: 'Decimal degrees, such as 46.7712. Right-click the spot in OpenStreetMap or Google Maps to copy it.', tip: 'Places the pin in the schema and on the map; without coordinates the map looks the address up.', }, longitude: { label: 'Longitude', description: 'Decimal degrees, such as 23.6236.', tip: 'With the latitude, places the pin in the schema and on the map.', }, opening_hours: { label: 'Opening hours', description: 'One line per rule: the days, then the hours or "closed". Under the box, each line as it will be read; a line that cannot be read is left out, and says so.', tip: 'Days as Mo, Mon or Monday, in ranges (Mon-Fri, Monday to Friday) or lists (Mon, Wed, Fri). Hours as 09:00-17:00, 9am-5pm or 9-17, several on a line for a break (09:00-12:00, 13:00-17:00), "closed" or "open 24 hours".', }, about_page: { label: 'About page', description: 'The page that describes the business; its schema becomes an AboutPage.', tip: 'An AboutPage schema tells search engines and assistants where the business describes itself.', }, contact_page: { label: 'Contact page', description: 'The page with the contact details; its schema becomes a ContactPage.', tip: 'A ContactPage schema points assistants to the page with the address and phone.', }, show_map: { label: 'Map in the contact block', description: 'Show a map around the coordinates in [recomaze_contact_info].', tip: 'Loaded only on pages that use the shortcode with the map, from the map service chosen under Contact.', }, map_provider: { label: 'Map service', description: 'Who draws the maps of the contact block, the store locator and the preview here.', tip: 'OpenStreetMap needs no account or key. Google Maps needs a browser key from Google Cloud with the Maps Embed API and the Maps JavaScript API enabled; it may bill above the free tier.', }, google_maps_key: { label: 'Google Maps API key', description: 'The browser key from Google Cloud. Printed in the pages that show a map, as Google intends browser keys to be; restrict it to this domain in Google Cloud.', tip: 'Without a key the maps stay on OpenStreetMap even with Google Maps selected.', }, }; export const LLMS: Record< | 'post_types' | 'taxonomies' | 'limit' | 'description' | 'extra' | 'full_enabled' | 'full_limit', OptionCopy > = { post_types: { label: 'Post types', description: 'Each one becomes a section of the index, the most recently updated first.', tip: 'Pages and posts are the usual choice; products get their price and options in the summary.', }, taxonomies: { label: 'Taxonomies', description: 'Archives listed as sections, most used first, with their descriptions.', tip: 'Useful when a category page is the best answer to a broad question, such as a whole product range.', }, limit: { label: 'Entries per section', description: 'How many of each post type or taxonomy the index lists.', tip: 'Agents read the whole file on every visit; a few hundred entries is plenty. Raise it for a catalogue that is the point of the site.', }, description: { label: 'Site summary', description: 'The line under the title. Empty, the tagline from Settings → General is used.', tip: 'One sentence saying what the site is and who it is for, the way you would introduce it to a stranger.', }, extra: { label: 'Extra content', description: 'Markdown appended at the end of llms.txt: more links, a note for agents, a contact line.', tip: 'Keep the llms.txt shape: headings with ##, then one "- [title](url): summary" per line.', }, full_enabled: { label: 'Serve llms-full.txt', description: 'The text of the newest entries in one file, linked from llms.txt.', tip: 'Agents that cannot crawl pages one by one read this instead. Off, the file answers 404.', }, full_limit: { label: 'Entries in llms-full.txt', description: 'How many of each post type carry their full text.', tip: 'Each entry is up to fifteen thousand characters, so fifty posts make a file of a few hundred kilobytes.', }, };