# Config Reference (config.toml)

## Config Reference

**File:** `src/config/config.toml` · **Skill level:** Beginner

`config.toml` holds every site-wide setting: your business details, the header and footer layouts, the forms, the estimator and booking rules, SEO, and more. 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. Most keys have a comment beside them; this page explains them all in one place, with the value Homio ships.

Values marked `# sample` or `PLACEHOLDER` in the file must be replaced before you launch.

<Aside type="note">
  `npm run dev` picks up a saved change to `config.toml` and reloads the page.
  Restart it after you change `trailingSlash`, anything in
  `[settings.multilingual]`, or `src/config/fonts.json`: those are read only
  when the server starts.
</Aside>

### Site Identity
Table: `[site]`

| Key                | Ships as                 | What it does                                                                                   |
| ------------------ | ------------------------ | ---------------------------------------------------------------------------------------------- |
| `title`            | `"Homio"`                | Brand name. `{brand}` in the footer copyright, structured data, social cards, and the business name when `[business] name` is empty. The home page title comes from its own `metaTitle` |
| `description`      | A theme description      | Default description for search results and social previews                                    |
| `tagline`          | A theme tagline          | Added to every page title ("Pricing - your tagline") and social titles. Replace it with a short line about your business. A page turns it off with `disableTagline: true` |
| `taglineSeparator` | `""`                     | Text between page title and tagline. Empty uses `" - "`                                        |
| `baseUrl`          | `"https://example.com"`  | **Placeholder.** Your live address. Canonical links, the sitemap, `robots.txt`, RSS feeds, `llms.txt`, and social URLs are built from it, and `npm run build` warns while it is `example.com`. A `SITE_URL` environment variable on the build overrides it |
| `logo`             | `""`                     | Path to a logo image that replaces the built-in mark (SVG or PNG). Empty draws the mark from `src/lib/brandMark.ts` |
| `logoText`         | `"homio"`                | Text next to the mark, shown exactly as typed                                                  |
| `logoWidth`, `logoHeight` | `"28px"`          | Logo image size. Used only when `logo` is set                                                  |
| `trailingSlash`    | `true`                   | URLs end with `/` (`/pricing/`). Restart the dev server after a change                         |
| `[site.favicon] path`  | `"/images/favicons"` | Where the generated favicons go. Leave it as it is                                             |
| `[site.favicon] image` | `"/images/favicon.svg"` | Source image for `npm run generate-favicons` (`src/assets/images/favicon.svg`)              |

Details: [Site Identity & Logo](/homio/customization/site-identity-logo/).

### Business Details
Tables: `[business]`, `[business.address]`, `[business.geo]`, `[business.hours]`

One source for your company name, phone, email, address, and opening hours. The header, the mobile action bar, the footer, the contact page, the area pages, the booking form, the structured data, and `llms.txt` all read them from here.

| Key            | Ships as                 | What it does                                                         |
| -------------- | ------------------------ | -------------------------------------------------------------------- |
| `name`         | `""`                     | Business name. Empty uses `site.title`                               |
| `legalName`    | `""`                     | Optional legal name for structured data                              |
| `type`         | `"LocalBusiness"`        | The schema.org business type                                         |
| `phone`        | `"+15550100199"` (sample) | Phone for call links, in E.164 format. Empty hides every call link  |
| `phoneDisplay` | `"(555) 010-0199"` (sample) | How the phone is written on the page                              |
| `sms`, `smsDisplay` | sample numbers      | Optional number for "Text" links. Empty hides them                   |
| `email`        | `"hello@example.com"`    | **Placeholder.** Your email                                          |
| `priceRange`   | `"$$"`                   | Shown in structured data                                             |
| `timezone`     | `"America/New_York"`     | Time zone for "Open now" and booking dates                           |
| `closedDates`  | two sample holidays      | Days with no bookings (`YYYY-MM-DD`)                                 |
| `[business.address]` | sample address     | `show`, `street`, `locality`, `region`, `postalCode`, `country`. `show = false` hides the street and postal code everywhere |
| `[business.geo]` | empty                  | Optional `latitude` and `longitude`                                  |
| `[business.hours]` | sample hours         | `mon` to `sun`, 24-hour `"HH:MM-HH:MM"`. Empty is closed             |

Every key, its format, and where it appears: [Business Info](/homio/customization/business-info/).

### Search Engines
Tables: `[seo]`, `[seo.schema]`, `[seo.robotsTxt]`, `[seo.ai]`, `[seo.sitemap]`

| Key                          | Ships as  | What it does                                                                                 |
| ---------------------------- | --------- | -------------------------------------------------------------------------------------------- |
| `author`                     | `""`      | Default author meta tag. Empty uses the business name                                        |
| `keywords`                   | 8 samples | Default keywords for pages without their own `keywords`. Use your services and towns         |
| `robots`                     | `"index, follow, max-snippet:-1, ..."` | Default robots meta tag. Lets search and AI answers quote pages and show images in full |
| `[seo.schema] enable`        | `true`    | Structured data (JSON-LD) on every page: business, website, page, and services, areas, and prices where they apply |
| `[seo.schema] faqPage`       | `true`    | FAQ markup on `/faq/`                                                                         |
| `[seo.robotsTxt] enable`     | `true`    | Builds `/robots.txt`                                                                          |
| `[seo.robotsTxt] disallow`   | `[]`      | Paths crawlers must skip                                                                      |
| `[seo.robotsTxt] aiSearch`   | `true`    | `false` asks AI answer engines (ChatGPT search, Claude, Perplexity, and others) not to fetch your pages |
| `[seo.robotsTxt] aiTraining` | `true`    | `false` asks crawlers that collect content to train AI models to stay away                   |
| `[seo.robotsTxt] contentSignals` | `false` | `true` adds a `Content-Signal` line with the two choices above                             |
| `[seo.ai] llmsTxt`           | `true`    | Builds `/llms.txt` and `/llms-full.txt` per language, with your business facts first         |
| `[seo.ai] markdownPages`     | `true`    | A Markdown copy of each service, area, project, post, job, pricing, FAQ, and guarantee page at `<page>.md` |
| `[seo.ai] indexNowKey`       | `""`      | An 8 to 128 character key turns on IndexNow; run `npm run indexnow` after each deploy        |
| `[seo.sitemap] enable`       | `true`    | Builds `/sitemap-index.xml`                                                                   |
| `[seo.sitemap] exclude`      | `["book/thanks"]` | Folder names to leave out of the sitemap                                             |

Details: [SEO & AI Visibility](/homio/customization/seo-ai-visibility/).

### General Settings
Table: `[settings]`

| Key                   | Ships as                 | What it does                                                                     |
| --------------------- | ------------------------ | -------------------------------------------------------------------------------- |
| `blogFolder`          | `"blog"`                 | Folder name of the blog. Changing it also means renaming the folders in `src/content/` and `src/pages/[...lang]/` and the collection in `src/content.config.ts`. Most sites keep it |
| `servicesFolder`      | `"services"`             | The same, for services                                                           |
| `blogPagination`      | `6`                      | Posts per blog list page                                                         |
| `pagination`          | `8`                      | Items per page on other paginated lists                                         |
| `stickyHeader`        | `true`                   | Keeps the header pinned while scrolling (the announcement bar scrolls away)      |
| `contactFormAction`   | `"https://formsubmit.co/your-email@example.com"` | **Placeholder.** Where the contact form (and, by default, the booking form) sends its data. `npm run dev` and `build` warn until you change it |
| `contactFormProvider` | `"formsubmit.co"`        | `"formsubmit.co"`, `"formspree"`, or `"netlify"`                                 |
| `footerDescription`   | `""`                     | Footer description. Empty uses `footer.description` from `src/i18n/<language>.json` |

Details: [Forms](/homio/customization/forms/).

### Header And Footer Layouts
Table: `[settings.layout]`

| Key      | Ships as    | Values                                         |
| -------- | ----------- | ---------------------------------------------- |
| `header` | `"default"` | `default`, `simple`, `centered`, `utility`     |
| `footer` | `"default"` | `default`, `minimal`, `large`, `columns`       |

A page's `headerLayout` or `footerLayout` frontmatter wins. See [Header & Mobile Bar](/homio/customization/header/) and [Footer & CTA Band](/homio/customization/footer/).

### Smooth Scroll
Table: `[settings.smoothScroll]`

Smooth scrolling powered by Lenis. It ships **off** (`enable = false`): the site uses the browser's normal scrolling. `respectReducedMotion` keeps it off for visitors who ask for less motion; `duration` (`1.1`, higher feels slower) and `easing` (`expo`, `linear`, `easeOutQuad`, `easeOutCubic`) set the feel. Leave `smoothWheel`, `syncTouch`, `wheelMultiplier`, `touchMultiplier`, `anchors`, `autoRaf`, and `stopInertiaOnNavigate` as they are unless you know Lenis.

### Light And Dark Mode
Table: `[settings.colorScheme]`

| Key        | Ships as   | What it does                                                                  |
| ---------- | ---------- | ----------------------------------------------------------------------------- |
| `default`  | `"system"` | `system` (follows the visitor's device), `light`, or `dark`, until a visitor picks one |
| `switcher` | `true`     | Shows the light/dark button in the header, the mobile menu, and the footer     |

Details: [Colors & Fonts](/homio/customization/colors-fonts/).

### Cookie Banner
Table: `[settings.cookieConsent]`

| Key        | Ships as | What it does                                                                  |
| ---------- | -------- | ----------------------------------------------------------------------------- |
| `enable`   | `true`   | Shows the cookie banner and holds `data-consent` scripts until visitors choose |
| `revision` | `1`      | Raise it by 1 when your cookie use changes, to ask every visitor again       |

The banner's copy is in `src/content/sections/english/cookie-consent.md` (and `french/`). If you turn the banner off, also set `enable` to `false` on the "Cookie settings" item in the Legal column of the footer menus. Details: [Cookies & Analytics](/homio/customization/cookies-analytics/).

### Page Actions And AI Links
Table: `[settings.pageActions]`

| Key         | Ships as | What it does                                                                                  |
| ----------- | -------- | --------------------------------------------------------------------------------------------- |
| `enable`    | `true`   | The **Copy page** menu on blog posts: copy as Markdown, open the Markdown copy, or ask an assistant. Needs `[seo.ai] markdownPages` |
| `footer`    | `false`  | A footer row with AI links and `llms.txt` on every page. Off for most local businesses       |
| `providers` | `["chatgpt", "claude", "perplexity", "grok"]` | Assistants offered in "Ask". Empty hides the "Ask" links             |

### Animations
Table: `[settings.animation]`

Content fades in with a small rise as it scrolls into view, once.

| Key                    | Ships as                | What it does                                       |
| ---------------------- | ----------------------- | -------------------------------------------------- |
| `enable`               | `true`                  | Turns the reveal animations on or off              |
| `respectReducedMotion` | `true`                  | Shows content without animation for visitors who ask for less motion |
| `easing`               | `"cubic-bezier(0.215, 0.61, 0.355, 1)"` | The animation curve                |
| `duration`             | `"600ms"`               | Reveal duration                                    |
| `distance`             | `"0.75rem"`             | How far content rises while fading in              |
| `rootMargin`, `threshold` | `"0px 0px -8% 0px"`, `0.14` | How early an element starts animating     |

Details: [Animations](/homio/customization/animations/).

### Estimator
Table: `[settings.estimator]`

The instant estimator on the pricing page, the service pages, and the estimate sections. Rates, discounts, and add-ons are not here: they are in `src/content/pricing/`.

| Key               | Ships as    | What it does                                                         |
| ----------------- | ----------- | -------------------------------------------------------------------- |
| `enable`          | `true`      | Turns the estimator on                                               |
| `currency`        | `"USD"`     | ISO 4217 currency code, one for every language                       |
| `currencyDisplay` | `"symbol"`  | `symbol` ($ or $US), `narrowSymbol` ($ in every language), or `code` (USD) |
| `bookUrl`         | `"/book/"`  | Where "Book this visit" goes, with the selection in the address      |
| `ticketPrefix`    | `"EST"`     | Code on the estimate ticket, for example `EST-4K7Q2`                 |
| `animateTotal`    | `true`      | Counts between totals. Always off for visitors who ask for less motion |

Details: [Pricing & Estimator](/homio/customization/pricing-estimator/).

### Booking Request Form
Table: `[settings.booking]`

The form on `/book/`. It posts through the same provider as the contact form (`contactFormProvider`); its copy is in `src/content/sections/english/booking-section.md`.

| Key           | Ships as           | What it does                                                              |
| ------------- | ------------------ | ------------------------------------------------------------------------- |
| `enable`      | `true`             | Turns the booking form on                                                 |
| `formAction`  | `""`               | Endpoint for booking requests. Empty uses `contactFormAction`. Set it to send bookings to another inbox or form |
| `thankYouUrl` | `"/book/thanks/"`  | Where the form lands when JavaScript is off                               |
| `minLeadDays` | `1`                | Earliest date: today plus this many days                                  |
| `maxDays`     | `60`               | Latest date: today plus this many days                                    |
| `zipPattern`  | `"^\\d{5}$"`       | Postal code check (a regular expression). UK example: `"^[A-Za-z0-9 ]{5,8}$"` |
| `checkArea`   | `true`             | Tells visitors whether their ZIP code is in one of your service areas     |

Details: [Booking Request](/homio/customization/booking-request/).

### Layout Switcher (Demo Only)
Table: `[settings.layoutSwitcher]`

`enable = true` adds a floating **Change layout** button that previews every layout of the section in view. It is for the theme's demo site. Keep `enable = false` on your own site: the pages then render only the layouts chosen in your content files. To change how a section looks, set `options.layout`: see [Section Layouts](/homio/customization/section-layouts/).

### Copyright
Table: `[settings.copyright]`

`enable` (`true`) shows the copyright line in the footer. `text` (`""`) overrides `footer.copyright` from the i18n files for every language. In both, `{year}` becomes the year of the build and `{brand}` the `site.title`.

### Newsletter
Table: `[settings.subscription]`

The Mailchimp signup used by the newsletter section on the blog, the `default` and `large` footers, and the CTA band's `newsletter` layout.

| Key                 | Ships as          | What it does                                                                   |
| ------------------- | ----------------- | ------------------------------------------------------------------------------ |
| `enable`            | `true`            | `false` hides every signup form and the newsletter section                     |
| `title`             | `""`              | Empty uses `subscription.title` from the i18n files                            |
| `note`              | `""`              | The consent line under the field. Empty uses `subscription.note`               |
| `formAction`        | a placeholder URL | **Placeholder.** Your Mailchimp embedded form action. Change each `&amp;` in the copied URL to `&`. `npm run dev` shows a warning inside each form until it is set |
| `mailchimpTagValue` | `""`              | Optional Mailchimp tag id added to every signup                                |

### Languages
Table: `[settings.multilingual]`

| Key                    | Ships as | What it does                                                          |
| ---------------------- | -------- | --------------------------------------------------------------------- |
| `enable`               | `true`   | `false` builds only the default language. Then run `npm run remove-multilingual` to delete the French files |
| `defaultLanguage`      | `"en"`   | Language served without a prefix                                     |
| `disableLanguages`     | `[""]`   | Languages to skip, for example `["fr"]`                              |
| `showDefaultLangInUrl` | `false`  | `true` adds the prefix to the default language too (`/en/pricing/`)  |

Restart the dev server after any change here. Details: [Internationalization](/homio/customization/internationalization/).

### Header Button
Table: `[settings.navigationButton]`

The main button at the right of the header. The mobile action bar uses the same button.

| Key      | Ships as   | What it does                                                                 |
| -------- | ---------- | ---------------------------------------------------------------------------- |
| `enable` | `true`     | Shows the button                                                             |
| `label`  | `""`       | Empty uses `navigation.buttonLabel` from the i18n files ("Get a price"). A value here is used in every language |
| `url`    | `"/book/"` | Where it goes. The button is hidden on that page itself                      |

### Mobile Action Bar
Table: `[settings.mobileActionBar]`

The bar fixed to the bottom of the screen on phones (below 768 px), with **Call** and the header's main button.

| Key              | Ships as                 | What it does                                                    |
| ---------------- | ------------------------ | --------------------------------------------------------------- |
| `enable`         | `true`                   | Shows the bar                                                   |
| `showCall`       | `true`                   | The Call button, with `[business] phone`. Hidden when the phone is empty |
| `showText`       | `false`                  | A Text button. Needs `[business] sms`                           |
| `hideOn`         | `["/book/", "/contact/"]` | Path prefixes where the bar is left out (without the language prefix) |
| `hideNearFooter` | `true`                   | The bar slides away while the footer is visible                 |

Details: [Header & Mobile Bar](/homio/customization/header/#the-mobile-action-bar).

### Secondary Header Link
Table: `[settings.navigationSecondaryLink]`

A text link before the header button, in every header layout from 1320 px wide. It ships off (`enable = false`). `label` (`""`) uses `navigation.secondaryLabel` ("Contact"); `url` is `"/contact/"`.

### Code Blocks And Tables Of Contents
Tables: `[settings.markup.codeBlocks]`, `[settings.markup.tableOfContents]`

- `[settings.markup.codeBlocks] theme`: `auto` (follows light and dark mode, the default) or `dark` (a dark code window in both modes), for fenced code in Markdown.
- `[settings.markup.tableOfContents]`: the "On this page" list on blog posts and text pages such as the privacy policy. It ships with `enable = true`, `startLevel = 1`, `endLevel = 5`, `ordered = false`, and `expanded = false`.

### Social Previews
Table: `[opengraph]`

| Key              | Ships as                    | What it does                                                         |
| ---------------- | --------------------------- | -------------------------------------------------------------------- |
| `image`          | `"/images/og-image.jpg"`    | Shared preview image (`public/images/og-image.jpg`), used when a page has no `image` and no generated card |
| `generateImages` | `true`                      | During `npm run build`, renders a 1200×630 card (logo, section, title, description) for every page without an `image` |
| `theme`          | `"light"`                   | `light` or `dark` palette for the generated cards and `npm run generate-og-image` |
| `ogLocale`       | `"en_US"`                   | Fallback locale. Each language sets its own `ogLocale` in `src/config/language.json` |
| `ogType`         | `"website"`                 | Open Graph type                                                      |
| `twitter`, `twitterCard` | `""`, `"summary_large_image"` | X (Twitter) handle and card type                             |

Details: [Site Identity & Logo](/homio/customization/site-identity-logo/#social-preview-images).

### 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, change each tracking `<script>` to `<script type="text/plain" data-consent="analytics">` (or `"marketing"`) so it waits for consent; the comment above `[head]` shows an example. See [Cookies & Analytics](/homio/customization/cookies-analytics/).

### The Other Files In `src/config/`
| File                              | What it holds                                                                        | Page                                                        |
| --------------------------------- | ------------------------------------------------------------------------------------ | ----------------------------------------------------------- |
| `menu.en.json`, `menu.fr.json`    | The header menu (with the Services and Areas dropdowns) and the footer link columns | [Menus](/homio/customization/menus/)                        |
| `language.json`                   | The languages: name, code, content folder, order, and `ogLocale`                     | [Internationalization](/homio/customization/internationalization/) |
| `fonts.json`                      | The three fonts: body, headings, and numbers                                         | [Colors & Fonts](/homio/customization/colors-fonts/#fonts)  |
| `social.json`                     | Social links and their icons (`main` list)                                           | [Footer & CTA Band](/homio/customization/footer/#social-links) |

Colors are not in `src/config/`: they are tokens in `src/styles/theme.css`.

### Do It With AI
```text
Explain each table of src/config/config.toml in one line, then list every value marked
"# sample" or "PLACEHOLDER" that I must replace before launch, and the current value of each.
Don't change anything yet.
```