Config Reference
File: src/config/config.toml · Skill level: Beginner
config.toml holds every site-wide setting. It is grouped into tables: a line in [brackets] starts a table, and every key = value line below it belongs to that table until the next one. The file has a comment beside most keys; this page explains them in one place.
In the Tina edition, these keys are under Site settings at /admin/. In the Sanity edition, most are under Site settings in the Studio, which win over this file. Favicons, the language settings, and the collection folder names stay in config.toml there.
Site Identity
Table: [site]
| Key | What it does |
|---|---|
title | Site name. Used in page titles, the logo’s alt text, structured data, llms.txt, and the outlined wordmark at the bottom of the wordmark footer |
description | Default description for search results and social previews. Empty uses each language’s own, in src/i18n/<lang>.json. A value here is used for every language. |
tagline | Added after every page title (“Pricing - your tagline”). Empty uses each language’s own, in src/i18n/<lang>.json. A value here is used for every language. A page turns it off with disableTagline: true |
taglineSeparator | Text between title and tagline. Empty uses " - " |
baseUrl | Your live address, for example "https://www.your-domain.com". Ships as the placeholder "https://example.com", and npm run build warns until you change it. A SITE_URL environment variable on the build overrides it |
logo | Path to the logo for light backgrounds |
logoAlternate | Path to the logo for dark backgrounds: the dark footers, and the transparent header over a photo |
logoText | Text next to the logo. Empty shows only the image |
logoWidth, logoHeight | Logo size, for example "132px" and "32px" |
trailingSlash | true makes every URL end with / (/pricing/) |
[site.favicon] image | Source image for npm run generate-favicons. Leave path as it is |
Search Engines
Tables: [seo], [seo.robotsTxt], [seo.ai], [seo.localBusiness], [seo.sitemap]
| Key | What it does |
|---|---|
author | Default author meta tag |
keywords | Default keywords for pages without their own keywords |
robots | Default robots meta tag. The shipped value lets search and AI answers quote and preview pages |
[seo.robotsTxt] enable | Builds /robots.txt |
[seo.robotsTxt] disallow | Paths crawlers must skip, for example ["/drafts/"] |
[seo.robotsTxt] aiSearch | false asks the crawlers of AI answer engines (ChatGPT search, Claude, Perplexity, and others) not to fetch your pages |
[seo.robotsTxt] aiTraining | false asks crawlers that collect content to train AI models to stay away |
[seo.ai] llmsTxt | Builds /llms.txt and /llms-full.txt, one per language |
[seo.ai] markdownPages | Builds a Markdown copy of each service, project, post, open role, FAQ, pricing, and legal page at <page>.md |
[seo.localBusiness] type | The schema.org business type, for example "HomeAndConstructionBusiness", "Electrician", or "RoofingContractor" |
[seo.localBusiness] areaServed | The towns or regions you install in. Ships with sample town names |
[seo.localBusiness] priceRange, openingHours | Optional. openingHours uses the schema.org format, for example "Mo-Fr 08:00-18:00" |
[seo.sitemap] enable | Builds /sitemap-index.xml |
[seo.sitemap] exclude | Folder names to leave out of the sitemap |
The business name in the structured data is site.title; its address, phone, and email come from [settings.contactInfo]. Details: SEO & AI Visibility.
General Settings
Table: [settings]
| Key | What it does |
|---|---|
blogFolder, serviceFolder, projectsFolder, testimonialFolder, teamFolder, careersFolder | Folder names of the collections. Changing one also means renaming the content and route folders and the collection in src/content.config.ts. Most sites keep them |
pagination | Posts per blog list page |
stickyHeader | Keeps the header bar at the top of the window while you scroll. The rows above it (top bar, info row, announcement strip) scroll away; once the bar reaches the top, only its colours change |
contactFormAction | Where the quote form sends its data. The shipped value is a placeholder, and npm run dev and npm run build print a [forms] warning until you change it. See Forms |
contactFormProvider | "formsubmit.co" (default), "formspree", or "netlify" |
footerDescription | Text under the logo in the cta and contact footer layouts. Empty uses footer.description from src/i18n/<language>.json |
Smooth Scroll
Table: [settings.smoothScroll]
Smooth scrolling powered by Lenis. It stays off on touch devices.
| Key | What it does |
|---|---|
enable | false gives the browser’s normal scrolling |
respectReducedMotion | Switches it off for visitors who ask for less motion |
duration | How long the glide lasts. Higher feels slower |
easing | expo, linear, easeOutQuad, or easeOutCubic |
smoothWheel, syncTouch, wheelMultiplier, touchMultiplier, anchors, autoRaf, stopInertiaOnNavigate | Finer settings. Smooth Scroll explains each one |
Animations
Table: [settings.animation]
| Key | What it does |
|---|---|
enable | Fade-in animations as content scrolls into view, and the slow drift (parallax) of full-width photos. A page turns the fade-in off for itself with scrollReveal: false in its frontmatter, as the main homepage does |
respectReducedMotion | Shows content without animation for visitors who ask for less motion |
duration | Empty keeps each element’s own timing; a value such as "900ms" sets one duration for all |
distance, blur, easing | How far content moves in, how blurred it starts, and with which curve |
rootMargin, threshold | How early an element starts animating |
Cursor
Table: [settings.cursor]
enable = true adds an animated custom cursor that follows the mouse. It ships off, and it never shows on touch screens.
Cookie Banner
Table: [settings.cookieConsent]
| Key | What it does |
|---|---|
enable | Shows the cookie banner and holds consent-gated scripts until visitors choose |
revision | Raise it by 1 when your cookie use changes, to ask every visitor again |
Details: Cookies & Analytics.
Page Actions And AI Links
Table: [settings.pageActions]
| Key | What it does |
|---|---|
enable | The Copy page, View as Markdown, and Ask links on blog posts and on service, project, and job pages. false also removes the footer row. The Markdown links need [seo.ai] markdownPages = true |
footer | The Ask AI and llms row in every footer layout |
providers | Assistants offered: any of "chatgpt", "claude", "perplexity", "grok". Ships with all four. [] hides the “Ask” links |
Details: AI Links & llms.
Theme Demo Settings
Table: [settings.layoutSwitcher]
This table is used only by the theme’s own demo site. It has no effect on your build, so leave it as it is. To change how a section looks, set options.layout in its content file: see Section Layouts.
Footer
Tables: [settings.footer], [settings.footer.band], [settings.footer.cta], [settings.footer.contact], [settings.newsletter]
| Key | What it does |
|---|---|
[settings.footer] layout | wordmark (default), newsletter, cta, or contact. A page’s footerLayout frontmatter wins |
[settings.footer.band] | The call-to-action band that overlaps the top of the newsletter and cta layouts (in the cta layout it is the photo band below). enable = false turns it off on every page; it also hides on its own on pages that show a call to action section. url is where its button goes, and also the quote row of the wordmark layout. image and imageAlt are the arch photo in the newsletter layout’s band (empty image hides it). Its text is footer.band in the i18n files |
[settings.footer.cta] | The photo band of the cta layout: enable, title, label, and url of its closing line and button, and image and imageAlt of its photo (empty image hides it). Empty title and label use footer.cta.title and footer.cta.button from the i18n files; the project card is footer.cta.projects |
[settings.footer.contact] | The area check of the contact layout: postcodes, the postcode prefixes you cover (the shipped ones are placeholders), and url, the quote page it links to. An empty postcodes list sends visitors to the quote page |
[settings.newsletter] | enable, action, and provider (formsubmit.co, formspree, netlify, or "" for a plain form post) of the sign-up form in the newsletter layout. The shipped action is a placeholder: npm run dev and npm run build print a [forms] warning until you change it. See Forms |
Details: Footer.
Copyright
Table: [settings.copyright]
enable shows the copyright line in the footer. text overrides footer.copyright from the i18n files; {{ year }} is replaced with the year of the build.
Theme Credit
Table: [settings.themeCredit]
The theme credit in every footer layout, and the last line of llms.txt. It has enable, text, and url, and it is the same in every language. The part of text in [brackets] links to url:
[settings.themeCredit] enable = true text = "..." url = "..."Languages
Table: [settings.multilingual]
| Key | What it does |
|---|---|
enable | false builds only the default language |
defaultLanguage | Language served without a prefix ("en") |
disableLanguages | Languages to skip, for example ["fr"] or ["fr", "ar"] |
showDefaultLangInUrl | true adds the prefix to the default language too (/en/pricing/) |
Details: Internationalization.
Contact Details
Table: [settings.contactInfo]
address, email, phone, and hours. They are shown in the header’s contact row, the mobile menu, the footers, and the contact cards on /contact/, and they feed the structured data and llms.txt. Write them as plain text; the phone number becomes a tel: link on its own.
Mobile Menu Panel
Tables: [settings.headerOffcanvas], [settings.headerOffcanvas.button]
The slide-in panel that opens from the menu button on small screens: a short description, the menu links, your contact details, social icons, and a button. Empty description and label use headerOffcanvas from the i18n files.
Header Layout
Table: [settings.header]
layout: classic (default), transparent, floating, or promo. A page’s headerLayout frontmatter wins. See Header.
Header Button
Table: [settings.navigationButton]
The button at the right of the header (“Get a free quote”). It has enable, label, and url. An empty label uses navigation.buttonLabel from the i18n files.
Announcement
Table: [settings.announcementBar]
The citrus announcement strip at the top of the page. The promo header layout always shows it; enable = true also shows it above the classic header. label is the text for every language and accepts Markdown; empty uses header.announcement from the i18n files, and a page’s headerAnnouncement wins over both. See Header.
Tables Of Contents
Table: [settings.markup.tableOfContents]
enable, startLevel, endLevel, ordered, and expanded for an “On this page” list on blog posts and text pages such as the privacy policy. It ships off.
Social Previews
Table: [opengraph]
| Key | What it does |
|---|---|
image | Shared preview image, used when a page has no image |
ogLocale, ogType | Open Graph locale and type |
twitter, twitterCard | X (Twitter) handle and card type |
Custom Head Scripts
Table: [head]
content is pasted into the <head> of every page. Use it for analytics, verification tags, or extra stylesheets. With the cookie banner on, mark tracking scripts so they wait for consent: see Cookies & Analytics.