# Menus

## Menus

**Files:** `src/config/menu.en.json`, `src/config/menu.fr.json` · **Skill level:** Beginner

The header menu and the footer link columns live in one JSON file per language. `menu.en.json` is the English menu and `menu.fr.json` the French one. Keep the two files in the same shape: same items, same order, same URLs. Only the `name` and `label` texts differ.

Each file has two lists:

```json
{
  "header": [ ... ],
  "footer": [ ... ]
}
```

### Header Menu
Each item in `header` is one entry in the top menu. A trimmed copy of the shipped English menu:

```json
"header": [
  {
    "enable": true,
    "name": "Services",
    "url": "/services/",
    "hasChildren": true,
    "source": "trades",
    "limit": 6,
    "children": [
      { "enable": true, "name": "Who we serve", "url": "/industries/" },
      { "enable": true, "name": "How it works", "url": "/how-it-works/" }
    ]
  },
  { "enable": true, "name": "Pricing", "url": "/pricing/" },
  {
    "enable": true,
    "name": "Areas",
    "url": "/areas/",
    "hasChildren": true,
    "source": "areas",
    "limit": 8
  },
  { "enable": true, "name": "Reviews", "url": "/reviews/", "class": "hidden xl:flex" },
  {
    "enable": true,
    "name": "Company",
    "hasChildren": true,
    "children": [
      { "enable": true, "name": "About us", "url": "/about/" },
      { "enable": true, "name": "Projects", "url": "/projects/" },
      { "enable": true, "name": "Contact", "url": "/contact/" }
    ]
  }
]
```

| Key           | What it does                                                                                     |
| ------------- | ------------------------------------------------------------------------------------------------ |
| `enable`      | `false` hides the item without deleting it                                                       |
| `name`        | The text in the menu                                                                             |
| `url`         | Where it links. Write paths without the language: `/pricing/`, not `/fr/pricing/`. The French menu adds `/fr/` itself. A dropdown with a `url` also marks itself active on the pages under it |
| `hasChildren` | `true` makes the item a dropdown                                                                 |
| `children`    | The links inside the dropdown, each with `enable`, `name`, and `url`                             |
| `source`      | `"trades"` builds the Services mega menu from your services; `"areas"` lists your service areas. See [Header & Mobile Bar](/homio/customization/header/#the-services-mega-menu) |
| `limit`       | With `source`: the most services per trade (`6`) or areas (`8`) shown                            |
| `class`       | Extra classes for the item. `"hidden xl:flex"` hides **Reviews** below 1320 px, where the bar runs out of room |

### Dropdowns With Labelled Columns
A child that has its own `hasChildren` and `children` becomes a **labelled column** in the dropdown. Its `name` is the small heading above the column. The **Pages** menu uses this to list every page of the theme in five columns:

```json
{
  "enable": true,
  "name": "Pages",
  "hasChildren": true,
  "children": [
    {
      "enable": true,
      "name": "Homepages",
      "hasChildren": true,
      "children": [
        { "enable": true, "name": "Main homepage", "url": "/" },
        { "enable": true, "name": "Cleaning company", "url": "/home-cleaning/" },
        { "enable": true, "name": "Commercial cleaning", "url": "/home-commercial/" },
        { "enable": true, "name": "Handyman", "url": "/home-handyman/" }
      ]
    },
    {
      "enable": true,
      "name": "Booking & help",
      "hasChildren": true,
      "children": [
        { "enable": true, "name": "Book", "url": "/book/" },
        { "enable": true, "name": "Contact", "url": "/contact/" }
      ]
    }
  ]
}
```

Plain links and labelled columns can be mixed in one dropdown: the plain links come first, as one column without a heading. A dropdown of plain links only is one list, split into two columns above eight links. On phones, the columns become lists inside the mobile menu.

<Aside type="tip" title="Hide the Pages menu on your site">
  **Pages** is a catalog of the demo: it links to the four homepages, the
  sample detail pages, and `/elements/`. Set its `"enable"` to `false` in both
  menu files before you launch.
</Aside>

### Footer Menus
`footer` is a list of link columns. Each has a `label` (the column heading) and a `list` of links:

```json
"footer": [
  {
    "label": "Services",
    "list": [
      { "enable": true, "name": "All services", "url": "/services/" },
      { "enable": true, "name": "Standard clean", "url": "/services/standard-cleaning/" },
      { "enable": true, "name": "Deep clean", "url": "/services/deep-cleaning/" }
    ]
  },
  {
    "label": "Areas",
    "source": "areas",
    "list": [{ "enable": true, "name": "All areas", "url": "/areas/" }]
  },
  {
    "label": "Legal",
    "list": [
      { "enable": true, "name": "Terms", "url": "/terms-conditions/" },
      { "enable": true, "name": "Privacy policy", "url": "/privacy-policy/" },
      { "enable": true, "name": "Cookie settings", "url": "#cookie-settings" }
    ]
  }
]
```

The shipped file has five columns: **Services**, **Company**, **Help**, **Areas**, and **Legal**. Two rules matter:

- **The last column holds the legal links.** Every footer layout shows it in its bottom row, next to the copyright, instead of as a column. Keep Legal last.
- **`"source": "areas"`** lists your service areas first, then the column's own links ("All areas"). The `large` footer turns this column into a row of areas.

Each footer layout uses the columns a little differently: `default` puts the first column (Services) in two columns beside your contact details, `minimal` shows the first two, and `columns` shows up to three link columns plus your contact details. See [Footer & CTA Band](/homio/customization/footer/).

The **Cookie settings** link (`#cookie-settings`) reopens the cookie banner. If you turn the banner off in `[settings.cookieConsent]`, set this item's `enable` to `false`.

### Keep Both Languages In Step
`npm run check-i18n` (also part of `npm run astro-check`) compares `menu.fr.json` with `menu.en.json` and reports a difference in the number of items, a `url`, or a `source`. So when you add, remove, or move a menu item, do it in both files.

JSON is strict: every item but the last in a list needs a comma after it, and every name and URL needs double quotes. A missing comma stops the site from building. See [File Formats](/homio/beginner/file-formats/).

### Do It With AI
```text
In src/config/menu.en.json and menu.fr.json: set "enable": false on the "Pages" header item,
remove [ITEMS] from the Company dropdown, and add a header link "[NAME]" ("[FRENCH NAME]") to
[URL] after Pricing. In the footer, make the Services column list only: [SERVICES]. Keep the
Legal column last and the Areas column's "source": "areas". Keep both files in the same
structure, then run npm run check-i18n.
```