# Groups

A group is a named collection of pages. Define your groups once in `settings/groups.md`, then control where they appear with `locations`.

## Defining groups

Groups live in `settings/groups.md`. Each group has a `name` (display label), a `slug` (URL-friendly key), locations where it's shown, and an ordered list of items:

```yaml
# settings/groups.md
groups:
  - name: Docs
    slug: docs
    indexPage: docs/docs-home.md
    locations:
      - sidebar:
          - group: docs
      - header
    items:
      - Getting Started: /docs/getting-started
      - Themes: /docs/themes
      - Navigation: /docs/navigation

  - name: Product Updates
    slug: product
    locations:
      - sidebar:
          - group: product
      - header
      - footer
    items:
      - Features: /features
      - Pricing: /pricing
      - Changelog: /changelog
```

Item order in the file controls display order everywhere — no numbers needed.

## Name vs slug

Every group has two identifiers:

| Field | Purpose | Example |
|---|---|---|
| `name` | Display label shown in header dropdowns, footer columns, and sidebar headings | `Product Updates` |
| `slug` | URL-friendly key used in frontmatter, sidebar references, and internal lookups | `product` |

The `slug` defaults to the kebab-case version of the `name` if not set. When `name` is already kebab-case (like `docs`), the slug is identical and can be omitted.

References throughout the system — `groupMember`, `sidebarGroupShown`, `group:` in header/footer, sidebar locations — accept either the name or the slug. Use whichever is convenient; sitemd resolves both.

## Locations

The `locations` field controls where a group appears on the site. There are three location types:

### Sidebar

Show the group's items as a sidebar on specific pages. List which pages get the sidebar:

```yaml
locations:
  - sidebar:
      - group: docs              # all pages with groupMember: [docs]
      - pages/features/roadmap.md  # a specific page (file path)
```

- `group: slug` — every page that has `groupMember` including that group gets the sidebar
- `path/to/page.md` — a specific page by file path, even if it's not a group member

Pages get a two-column layout with the group's items in a sidebar. The current page is highlighted. Items can have nested [sidebar anchors](#sidebar-anchors) that link to sections within the page.

### Header

Add `header` to locations and the group appears as a dropdown in `settings/header.md`:

```yaml
locations:
  - header
```

The build automatically adds a group entry to `header.md` if one doesn't exist. The dropdown is populated from the group's items. Removing the entry from `header.md` removes the `header` location from the group — see [bidirectional sync](#bidirectional-sync).

### Footer

Add `footer` to locations and the group appears as a column in `settings/footer.md`:

```yaml
locations:
  - footer
```

The build automatically adds a `group:` reference entry to `footer.md` if one doesn't exist. Removing the entry from `footer.md` removes the `footer` location from the group — see [bidirectional sync](#bidirectional-sync).

### No locations

Set `locations: []` to define a group that isn't shown anywhere automatically — useful for groups used only as data.

## Page membership

Pages declare which groups they belong to with `groupMember` in their frontmatter:

```yaml
groupMember:
  - docs
  - guides: Custom Sidebar Label
```

- Plain group name (`- docs`) — uses the page title as the sidebar label
- With custom label (`- guides: Custom Sidebar Label`) — overrides the label for that group's sidebar

### Sidebar overrides

Pages can override sidebar behavior with `sidebarGroupShown` in frontmatter:

```yaml
sidebarGroupShown: docs    # show this group's sidebar (overrides locations)
sidebarGroupShown: none    # suppress sidebar entirely
```

If a page has no `sidebarGroupShown` but is a member of a group with `sidebar` in its locations, the sidebar is shown automatically.

### Bidirectional sync

You can edit group membership and locations from either side — the build keeps everything in sync.

**Page membership:**

- **Add an item in groups.md** → build adds `groupMember` to the page's frontmatter
- **Add `groupMember` to a new page** → build adds the page to the group in groups.md (only for newly created pages)
- **Add `sidebarGroupShown` to a page** → build adds the page to the group's sidebar locations

Groups must be defined in `groups.md` first — adding `groupMember: [foo]` to a page does not create a `foo` group. If the referenced group doesn't exist, the membership is silently ignored.

New pages are appended to the end of the group's item list. Reorder by editing groups.md directly.

AI agents using `sitemd_pages_create` with `groupMember` automatically add pages to the group's sidebar navigation. The group is created automatically if it doesn't exist. For manual group management, use `sitemd_groups_add_pages`. See [MCP Server](/docs/mcp-server#sitemd_groups_add_pages) for parameters.

**Header and footer locations:**

- **Add `header`/`footer` to a group's locations in groups.md** → build adds the group entry to `header.md`/`footer.md`
- **Add a `- group: name` entry to header.md or footer.md** → build adds the matching location to the group in groups.md
- **Remove a group entry from header.md or footer.md** → build removes the matching location from groups.md
- **Remove `header`/`footer` from a group's locations** → build removes the group entry from the nav file

Edit whichever file is convenient — the other updates on the next build.

## Index pages

You can optionally set an `indexPage` for a group — a page that serves as the group's landing page. Footer group headings will link to this page when set.

```yaml
groups:
  - name: Docs
    slug: docs
    indexPage: docs/docs-home.md
    items:
      - ...
```

If no `indexPage` is set, footer group headings render as plain text (no link).

## Auto-creation

When you add a dropdown group to `settings/header.md`, sitemd automatically:

1. Creates the child pages if they don't exist
2. Creates a matching group in `groups.md` with `header` and `sidebar` in locations
3. Sets `groupMember` on each child page

You don't need to manually set up groups — just add items to your header nav and the group system takes care of the rest.

## Sidebar anchors

Add nested anchors under any sidebar item to link to sections within that page. Anchors appear as an expandable sub-list below the parent link.

```yaml
# settings/groups.md
items:
  - Getting Started: /docs/getting-started
    - Install the Plugin: #install-the-plugin
    - Set Up Your Project: #set-up-your-project
    - Build and Preview: #build-and-preview
  - Themes: /docs/themes
    - Customizing Colors: #customizing-colors
    - Typography: #typography
```

Each anchor entry is indented under its parent item. The format is `- Label: #anchor-id`, where the ID matches a heading on that page. Clicking an anchor navigates to the parent page and scrolls to that section.

Anchors are expand/collapse — click the chevron to toggle. The active page's anchors are always expanded automatically.

### Default display

Anchors are collapsed by default. To show all anchors expanded on load, set `anchorsDisplay`:

```yaml
groups:
  - name: Docs
    slug: docs
    anchorsDisplay: expanded
    items:
      - ...
```

| Value | Behavior |
|---|---|
| `collapsed` | Anchors hidden until expanded (default). Active page's anchors always expand automatically. |
| `expanded` | All anchors visible on load. |

### Finding anchor IDs

Every heading on a page generates a URL-friendly ID automatically. `## Install the Plugin` becomes `#install-the-plugin`. To find the exact ID, inspect the heading in your browser or check the built HTML in `site/`.

See [anchor links](/docs/pages-and-content#anchor-links) for more on how heading IDs work.

## Link targets

Append `+newtab` or `+sametab` to any link URL in groups.md to control window behavior:

```yaml
items:
  - API Docs: https://api.example.com +sametab
  - Preview: /demo +newtab
```

Default: external links open in a new window, internal links open in the same window. See [Pages & Content](/docs/pages-and-content#link-targets) for details.

## Full reference

### Group fields

| Field | What it does |
|---|---|
| **name** | Display name shown in header dropdowns, footer columns, and sidebar headings. |
| **slug** | URL-friendly key used in frontmatter references (`groupMember`, `sidebarGroupShown`) and sidebar locations. Defaults to kebab-case of `name`. |
| **feed** | Set to `true` to generate an RSS feed at `/{slug}/feed.xml`. See [RSS Feeds](/docs/rss-feeds). |
| **indexPage** | File path of the page that serves as the group's landing page. Footer group headings link to this page. |
| **locations** | Where the group is shown: `sidebar:` (with page targets), `header`, `footer`. Defaults to sidebar on own members. |
| **items** | Ordered list of `Label: /slug` entries. Controls sidebar, dropdown, and footer order. Supports nested `- Label: #anchor` sub-items. |
| **itemOrder** | Set to `alpha` to sort items alphabetically. Default preserves the order as written in groups.md. |
| **anchorsDisplay** | Default expand/collapse state for sidebar anchors: `collapsed` (default) or `expanded`. |

### Page frontmatter fields

| Field | What it does |
|---|---|
| **sidebarGroupShown** | The group slug (or name) to display as sidebar, or `none` to suppress. |
| **groupMember** | List of group slugs (or names) this page belongs to. Supports custom labels with `slug: Label`. |


## Sidebar behavior

For details on how the sidebar UI works — search, anchor navigation, mobile integration, and scrolling — see the [Sidebar](/docs/sidebar) page.