# Collections (Services, Team, Journal & More)

## Collections

**Skill level:** Beginner · **Files:** `src/content/<collection>/<language>/`, defined in `src/content.config.ts`

A **collection** is a folder of similar entries: services, team members, journal posts, authors. Most entries are one file and one page. The list page of the collection (for example `/services/`) takes its title and section blocks from the `-index.md` file in the same folder (`-index.mdx` for the journal). Files whose name starts with `_` are ignored, so `_draft-post.md` never becomes a page.

Projects and photo series have their own page: see [Projects](/margo/customization/projects/).

### Add An Entry
<Steps>

1. Copy an existing entry in the folder, for example `src/content/services/english/packaging.md`.
2. Rename the copy. The file name becomes the URL (`/services/signage/`), unless you set `customSlug`.
3. Change the frontmatter values and the Markdown body. Keep the keys.
4. Add the same file name in `french/` and `arabic/` with the translated text.

</Steps>

To hide an entry, set `draft: true`. It still shows in `npm run dev`, but it is left out of the built site, the lists, the sitemap, and search. `draft: true` in a folder's `-index.md` hides the list page and every entry in that folder.

### Collection Reference
The fields every page accepts (`title`, `description`, `image`, `draft`, `customSlug`, SEO fields) work on every entry. The table lists the extra fields. Each entry file shows its fields with comments.

| Collection     | Folder          | URL                               | Extra fields                                                                       |
| -------------- | --------------- | --------------------------------- | ---------------------------------------------------------------------------------- |
| Services       | `services/`     | `/services/<file>/`               | `icon`, `imageAlt`, `category`, `weight`, `price`, `duration`, `deliverables`, `tools`, `process`, `related`, `faq`, `detail` |
| Team           | `team/`         | `/team/<file>/`                   | `profession`, `location`, `email`, `phone`, `social`, `weight`                     |
| Journal posts  | `blog/`         | `/blog/<file>/`                   | `date`, `updated`, `author`, `categories`, `tags`, `featured`, `imageDark`         |
| Authors        | `author/`       | (shown on posts)                  | `title` (the name), `role`, `image`, `description`, `links`                        |
| Projects       | `projects/`     | `/projects/<file>/`               | See [Projects](/margo/customization/projects/)                                     |

These folders hold only a `-index.md` file, the content of one page: `about-us/` (`/about/`), `testimonials/` (`/testimonials/`), `pricing/` (`/pricing/`), `faq/` (`/faq/`), and `contact/` (`/contact/`).

### Services
Each service file is one service page, and the services sections on the homepages and `/services/` list them in `weight` order (lowest first).

```yaml
# src/content/services/english/brand-identity.md
title: "Brand identity"
description: "A mark, a type system, and a colour palette..."
image: "/images/services/brand-identity.jpg"
imageAlt: "Two blank business cards on a dark wooden surface"
icon: "PenTool" # a Lucide icon name, or a local SVG path
weight: 1
price:
  from: "€9,200" # the final text; it counts up
  unit: "per project"
duration: "6–8 weeks"
deliverables:
  - "Logo and wordmark"
  - "Brand guidelines (PDF)"
tools: ["Research", "Sketching", "Typography"] # names from tools-section.md
process:
  - title: "Brief"
    description: "A half-day conversation..."
    duration: "Week 1"
related: ["ceramic-forms", "envelope-system"] # project ids
faq:
  - question: "Do you also name businesses?"
    answer: "Yes, when the brief needs it..."
```

The service page shows, in order: the page header with the starting price and `duration`, the cover, the Markdown body, the `deliverables` and `tools`, the `process` steps, the `related` projects, the `faq`, and the call to action. A part with an empty list is left out.

- `icon` is a [Lucide](https://lucide.dev/icons/) name, such as `PenTool`, or the path of a local SVG. It shows on the service cards and rows.
- `tools` takes the `name` of items in `src/content/sections/<language>/tools-section.md`. Each one shows with that item's icon, so spell the names the same way.
- `category` is a group name for your own use. No demo page shows it.
- Write prices as they should read in each language: `"€9,200"` in English, `"9 200 €"` in French.

**The `detail` block.** The headings and short lines around each list on a service page are written once, in `detail` in `src/content/services/<language>/-index.md`: `buttons` (under the page header line), `deliverables`, `tools`, `process`, `related` (with its `button`), and `faq`. A service file can add its own `detail:` block to change any part for that page only. Objects merge key by key, and lists replace the whole list. A button in `detail.buttons` with an empty `url` links to your booking page (`[settings.contactInfo] booking`).

### Team
`/team/` shows every member as a card, in `weight` order. Each member has a page at `/team/<file name>/` with the portrait, the bio (the Markdown body), the contact rows, and a strip of the other members.

```yaml
# src/content/team/english/elio-brask.md
title: "Elio Brask"
description: "Leads design at the studio..." # the line under the name, and the meta description
image: "/images/people/team-design-lead.jpg" # portrait, 4:5
profession: "Design lead"
location: "Rotterdam"
email: "elio@example.com" # remove the line to hide the row
weight: 1
social:
  - enable: true
    label: "Instagram"
    icon: "/images/icons/social/instagram.svg" # an SVG drawn in the text color, or a Lucide name
    url: "https://www.instagram.com/"
```

The team grid is `src/content/sections/<language>/team-grid-section.md`. Its options are `layout` (`grid` or `strip`), `items` (member ids in order; empty lists everyone), `limit`, and `columns` (`3` or `4` on large screens). A member file can change the strip on its own page with a `teamGridSection:` block.

### Testimonials
Testimonials are not separate files. The quotes are the `items` list of `src/content/sections/<language>/testimonials-section.md`, and the same list shows on `/testimonials/`, the about page, and the homepages.

```yaml
items:
  - quote: "Hugo spent a morning in the kiln room before he drew anything..."
    emphasis: "The labels read like our glaze notebook" # a phrase copied exactly from `quote`, set in a heavier weight
    name: "Joel Ashcombe"
    role: "Founder"
    company: "Marrow Kiln"
    image: "/images/people/client-1.jpg" # a square portrait, or "" for the name only
    rating: "5.0" # shown with one star; "" hides it
```

`proof` is the rating row in the heading (`rating`, `label`, and up to 3 portraits). `src/content/testimonials/<language>/-index.md` holds the page header and the blocks of `/testimonials/`.

<Aside type="caution" title="Use real testimonials only">
  The quotes, names, ratings, and review counts in the demo are samples.
  Replace them with what your clients really said, or remove them.
</Aside>

### Journal
The journal is the `blog` collection, at `/blog/`. Posts can be `.md` or `.mdx`; use `.mdx` for [shortcodes](/margo/customization/writing-content/).

```yaml
# src/content/blog/english/how-i-price-a-project.mdx
title: "How I price a project, and why I stopped counting hours"
description: "Fixed prices with a written scope..."
image: "/images/blog/desk-paper.jpg"
date: 2026-08-18
author: "Hugo Merrin"
categories:
  - Business
tags:
  - "pricing"
```

- **Featured post.** `featured: true` puts the post in the large card at the top of `/blog/`. Without it, the newest post is featured.
- **Categories and tags** get their own list pages, `/blog/category/<name>/` and `/blog/tag/<name>/`. The category chips above the posts come from `filter.categories` in `src/content/sections/<language>/blog-list-section.md`, in that order; categories missing there are added at the end.
- **`updated`** shows an "Updated" date on the post.
- **`imageDark`** is an optional cover for dark mode.
- **Automatic parts:** reading time, the table of contents, related posts (posts that share a category first), the tags, the **Copy page** menu, the author box, and the RSS feed at `/blog/rss.xml`.
- **Posts per page:** `blogPagination` in `config.toml` (6). The featured card takes the place of two cards on the first page.
- The journal page also shows the newsletter section. See [Forms](/margo/customization/forms/).

On the homepages, the journal section picks posts with `options.featured` (the post id of the large card), `options.items`, and `options.limit`.

### Authors
A post's `author: "Hugo Merrin"` is matched to `src/content/author/english/hugo-merrin.md`: the name in lowercase, with dashes. The author box at the end of the post shows when that file exists and has a `description`.

```yaml
# src/content/author/english/hugo-merrin.md
title: "Hugo Merrin"
role: "Independent brand designer and art director"
image: "/images/people/persona-designer.jpg" # optional
description: "Hugo designs identities, packaging, and print..."
links:
  - label: "Instagram"
    url: "https://www.instagram.com/"
```

### About Page
`src/content/about-us/<language>/-index.md` holds the page header and the blocks of `/about/`: `aboutSection`, `statsSection`, `servicesSection`, `testimonialsSection`, `logosSection`, and `ctaSection`. The portrait, name, paragraphs, and social links are in `src/content/sections/<language>/about-section.md`, and the work history rows in `experience-section.md`.

### Do It With AI
```text
Add a [service | team member | journal post | author] to src/content/[services | team | blog |
author]/english/ for: [DETAILS]. Copy the frontmatter keys of an existing entry in that folder,
keep its comments, and fill in my values. Use a file name that makes a good URL. Then create the
french and arabic versions with the same file name in the french/ and arabic/ folders, and run
npm run astro-check.
```