Editing the content
All the words and images of the site live in src/content/. You edit plain TypeScript files — quotes around text,
commas between items — and the site updates while npm run dev is running. No CMS is needed. (If you would rather
manage content in Sanity, Payload, Strapi or Directus, see Using a headless CMS.)
src/content/ site.ts name, description, domain, navigation, contact details, footer, social links pages/home.ts the copy of the home page pages/about.ts …and of every other page collections/*.ts services, projects, posts, careers, team, testimonials routes.ts the URL of every page types.ts the fields each kind of item hasYour details first
Section titled “Your details first”src/content/site.ts holds what appears on every page:
| Field | Shown where |
|---|---|
site.name |
Logo alt text, browser title suffix, share cards |
site.title |
Browser title of the home page |
site.description |
Search results and share cards, for pages without their own description |
site.url |
Set this to your domain before publishing. Share links, sitemap.xml and robots.txt are built from it |
navigation |
The menu in the header |
contact |
Email, phone, address, map link, opening hours — used on the Contact page and in the footer |
footer |
Footer columns and social links |
Links use routes (routes.about, routes.post("my-slug")) so a URL is written once and stays in sync.
Page copy
Section titled “Page copy”One file per page in src/content/pages/. Each exports an object with the sections of that page and a meta entry:
export const about = { meta: { title: "About", // browser tab: "About | Nitip" description: "We don't just market…", // search results and share cards }, hero: { … }, values: { … },};Change the text between the quotes, keeping the field names — the sections read them by name. Apostrophes are safe inside double quotes, and the demo uses the typographic ’. A double quote inside a double-quoted string needs a backslash before it.
Collections
Section titled “Collections”src/content/collections/ holds the lists the site builds pages from:
| File | What it feeds |
|---|---|
services.ts |
The Services page and one detail page per service |
projects.ts |
The Projects gallery and one case-study page per project |
posts.ts |
The Blog and one page per post |
careers.ts |
The Careers list and one page per role |
team.ts |
The team grid on About |
testimonials.ts |
The quotes slider on the home page |
The order of the items in the file is the order on the site. The home page shows the first few of each list; the
numbers are in src/app/page.tsx (services.slice(0, 5), projects.slice(0, 4)).
Adding an item
Section titled “Adding an item”Copy an existing entry, paste it below, and change the values. A project, for example:
{ slug: "acme-brand-refresh", // the URL: /projects/acme-brand-refresh title: "Acme Brand Refresh", year: "2025", image: "/images/project-acme.jpg", // a file in public/images services: [{ label: "Branding & Identity Design", slug: "branding-identity-design" }], summary: "One or two sentences shown in the gallery.", industry: "Retail", overview: { text: "…", image: "/images/project-acme-overview.jpg" }, process: { text: "…", images: ["/images/project-acme-process-1.jpg", "/images/project-acme-process-2.jpg"] }, result: { … },}slug must be unique and URL-safe (lower case, words joined by -). The page, the links to it and its entry in
sitemap.xml appear by themselves — there is nothing else to register.
The services on a project link to the service pages, so their slug has to match a service in services.ts.
Removing an item
Section titled “Removing an item”Delete the entry. If another item refers to it (a project pointing at a service you removed), your editor and
npm run build will say so.
What each field means
Section titled “What each field means”src/content/types.ts is the reference: it lists every field, which are optional (?), and a comment for the ones
that are not obvious. Your editor shows the same information while you type.
Post bodies
Section titled “Post bodies”A post body is a list of blocks, so the blog can render headings, paragraphs and lists consistently:
body: [ { type: "heading", text: "Why prototyping matters", bold: "prototyping" }, { type: "paragraph", text: "A paragraph of text.", highlight: "paragraph" }, { type: "list", ordered: true, // leave out for bullets items: [ [{ type: "paragraph", text: "First item." }], [{ type: "paragraph", text: "Second item, which can hold its own blocks." }], ], },]bold and highlight are separate runs of bold text, not markers inside text: a heading prints text and then
bold after it (text: "1. ", bold: "Start with a sketch"), a paragraph prints highlight in bold before text
(highlight: "Instant traffic: ", text: "drive qualified visitors…"). Mind the trailing space.
Images
Section titled “Images”- Put the file in
public/images/. - Refer to it in the content as
/images/<file>(the path starts atpublic).
Sizes and formats are handled for you: pages use next/image, which serves a scaled, modern format per device. Use
photos at least as wide as they appear (hero and project images: 2000 px or more, cards: 1200 px, avatars: 400 px),
in .jpg for photos and .png when you need transparency. Keep the demo’s aspect ratios (the layout crops to fit).
Two images sit outside the content because browsers and social networks ask for them by name:
| File | What it is |
|---|---|
src/app/icon.svg, favicon.ico, apple-icon.png |
The icon in the browser tab and on a phone’s home screen |
src/app/opengraph-image.png |
The picture shown when someone shares a link (1200 × 630 or larger) |
Describe the share image in src/app/opengraph-image.alt.txt.
Text that is not in content/
Section titled “Text that is not in content/”Interface words that never change per site — “Load More”, “Read More”, form labels, error messages — live with the
components in src/design-system/. Search for the phrase and you will find it. Everything a visitor reads as your
words is in src/content/.
After editing
Section titled “After editing”npm run buildA successful build means every page, link and image still resolves. See Going live for the rest of the checklist.