Case studies
Each case study is one JSON file in src/content/projects/. The file name is the URL: halden-rail.json becomes /case-study/halden-rail. Every file is checked against a schema when you build, so a missing field or a typo fails the build with a clear message instead of breaking a page.
You can write them by hand or in the Keystatic editor, which writes exactly the same files.
Directorysrc/
Directorycontent/projects/
- halden-rail.json the English case study
Directoryde/
- halden-rail.json the German translation, same file name
Directoryassets/projects/halden-rail/
- cover.jpg
Directorygallery/
- 0/src.jpg
- 1/src.jpg
Fields
Section titled “Fields”| Field | Type | Notes |
|---|---|---|
client |
text | The client’s name. Shown in the index, on cards and in the page header |
title |
text | The headline of the case study |
summary |
text, max 160 characters | One sentence for cards, search results and social previews |
year |
number | Year of the project |
order |
number | Position on the site. Lower comes first |
featured |
true / false | The first featured project leads the home page. Default false |
layout |
editorial, narrative, gallery |
Page layout, see below. Default editorial |
disciplines |
list, at least one | From the list in src/content/taxonomy.ts. Used by the work filters |
industry |
one value | From the list in taxonomy.ts. Used by the work filters |
services |
list of text, at least one | What you delivered, shown in the facts panel |
cover |
image path | Relative to the JSON file, for example ../../assets/projects/halden-rail/cover.jpg |
coverAlt |
text | Describe the image for people who can’t see it |
gallery |
list of { src, alt, caption? } |
Images in the story. Default none |
challenge |
text | The problem, one paragraph |
approach |
list of text, at least one | What you did. Each item is one paragraph |
outcome |
text | The result, one paragraph |
metrics |
list of { value, label, highlight }, max 4 |
Numbers that prove the outcome |
testimonial |
{ quote, name, role }, optional |
A client quote |
credits |
list of { role, name } |
Who worked on it |
The schema lives in src/content/schema.ts. If you add a field there, add it to keystatic.config.ts too so the editor offers it.
Layouts
Section titled “Layouts”Pick a layout per project with layout. They share the header, facts, outcome and credits, and differ in how the story and images are told.
| Layout | How it reads | Best for |
|---|---|---|
editorial |
Text and images alternate down the page, with a scroll-driven hero image | Most projects; the default |
narrative |
The story scrolls beside a sticky image that changes with each chapter | Process-heavy projects |
gallery |
Large images lead; the challenge and approach stay short in a sticky side column | Visual work: identity, photography, print |
narrative tells the story in three chapters: challenge, approach and outcome. The sticky frame shows the cover for the challenge, then the first and second gallery images, so give these projects at least two gallery images. On phones, and without JavaScript, each image sits inline above its chapter.
What the home page shows
Section titled “What the home page shows”- The hero features the first project with
featured: true, or the first project byorderif none is featured. - The client marquee lists every project’s
client. - Selected work lists the first five projects by
order, with a link to all of them. - Results shows up to four metrics, one per project, taken from metrics marked
"highlight": true. Mark at most one metric per project. - The quote comes from the Halden Rail case study, or the first project with a testimonial if that one is gone. Change the slug in
src/pages/[...lang]/index.astroto pick yours.
Related projects
Section titled “Related projects”The bottom of each case study suggests two others: shared disciplines count most, then the same industry, then order breaks ties. There is nothing to configure.
Disciplines and industries
Section titled “Disciplines and industries”The lists live in src/content/taxonomy.ts. To add one, add it there and add its label to the taxonomy section of every dictionary (en.ts, de.ts, id.ts); npm run check tells you if one is missing. The work page filters and the CMS dropdowns update by themselves.
Images
Section titled “Images”Put a case study’s images in src/assets/projects/<slug>/. Astro resizes them at build time and serves WebP in several sizes, so export large (2400px on the long side is plenty) and don’t pre-compress. The CMS does this for you when you upload.
Translating
Section titled “Translating”Copy the file into de/ or id/ with the same name and translate the text fields. Images are shared, so leave the paths as they are but add one ../ (the file is one folder deeper). See Translating content.