Skip to content
New: Customize your theme with an AI assistant. Read the guide

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.

Add An Entry

  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.

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.

CollectionFolderURLExtra fields
Servicesservices//services/<file>/icon, imageAlt, category, weight, price, duration, deliverables, tools, process, related, faq, detail
Teamteam//team/<file>/profession, location, email, phone, social, weight
Journal postsblog//blog/<file>/date, updated, author, categories, tags, featured, imageDark
Authorsauthor/(shown on posts)title (the name), role, image, description, links
Projectsprojects//projects/<file>/See 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).

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 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.

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: "[email protected]" # 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.

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/.

Journal

The journal is the blog collection, at /blog/. Posts can be .md or .mdx; use .mdx for shortcodes.

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.

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.

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

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.
Type something to search...