Editing the content — Ciketo Next.js
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, menu, contact details, footer, and the parts several pages share pages/home.ts the copy of the home page pages/about.ts …and of every other page collections/*.ts services, lanes, posts, testimonials, clients, legal pages routes.ts the URL of every page types.ts the fields each kind of item hasNot sure which file holds a piece of text? The page maps label every section of every page with its file.
Your details first
Section titled “Your details first”src/content/site.ts holds what appears on every page, and the sections that several pages share:
| Export | Shown where |
|---|---|
site.name |
Logo label for screen readers, browser title suffix, share cards |
site.title |
The browser title of the home page, and of any page without its own. |
site.description |
Search results and share cards of the home page, and of pages without their own description |
site.url |
Set this to your domain before publishing. Canonical links, share links, sitemap.xml and robots.txt are built from it. |
navigation |
The menu in the header (and the phone menu) |
headerAction |
The button on the right of the header (“Get a Quote”) |
clock |
The language of the date under the header clock: locale: "en-GB" shows “5 October 2026”. The time is the visitor’s own, on a 24-hour clock. |
contact |
Address, phone and e-mail (footer and Contact page), supportEmail (shown with the phone next to the services on Home), and the “Phone:” / “Email:” labels |
socials |
The Social column of the footer |
footer |
The tagline, the Company and Services columns, the Social and Contact column titles, the copyright line ({year} becomes the current year) and the legal links |
cta |
The dark call to action above the footer of Home, About, Services and Blog: label, title, text, photo and two buttons |
howItWorks |
“How It Works” on Home, Services and every service page: four steps, each with a title, description, label, info and photo |
industries |
“Industries We Serve” on Home and About: six industries and the five photos between them |
clientsIntro |
The label and the line before the client logos (Home, About) |
facts |
The four figures on Home and About (“15+ Years”, …): value, unit and description |
quoteForm |
The quote form on Home, Contact and every service page: label, title, text, photo, group titles, fields, consent line, button and messages (Forms) |
The demo’s e-mails (hello@example.com, support@example.com), phone number and address are placeholders: replace all
of them. The phone number is also the link of “Call Customer Service” in the call to action
(cta.secondary.href: "tel:+18005550147"). The footer’s Services column is a list of links, not the collection: update
it when you add, remove or rename a service.
Page copy
Section titled “Page copy”There is one file per page in src/content/pages/. Each exports an object with the sections of that page and, for
pages with a fixed URL, a meta entry:
export const about = { meta: { title: "About Us", // browser tab: "About Us | Ciketo" description: "A logistics partner that moves…", // search results and share cards (80–160 characters) }, hero: { … }, story: { … }, leader: { … },};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.
| File | Page |
|---|---|
home.ts |
Home: the hero and its figures, “Why Choose Us” with its quote, the services heading and the help card beside the list, the photo band, the blog heading and the FAQ (faq.items). It has no meta: its title is in src/app/page.tsx and its description is site.description. |
about.ts |
About: the hero, “Who we are” and the leader’s message (leader) |
services.ts |
Services: the title and the words in each row (“Explore”, “Key Benefits”) |
service.ts |
The words shared by every service page: the label, “Our solutions”, the “Lanes” after the service name, “Departure:” and “Arrival:”, and the photo next to the key benefits |
blog.ts |
Blog, with the text screen readers hear while more posts load |
post.ts |
The words shared by every post: “Date:” and “Other Posts” |
contact.ts |
Contact: title, text, photo, the “Contact” column title and the business hours (hours.rows) |
legal.ts |
“Last Updated:” on the legal pages |
not-found.ts |
The 404 page |
The Home hero’s figures are copy too (hero in home.ts): the “98.5% on time” pill, the booking note, the
“Enterprise accounts” card (the four names under it are the first four clients) and “Lanes Open”. The lane card at its
bottom right shows the first lane in lanes.ts.
Collections
Section titled “Collections”src/content/collections/ holds the lists the site builds pages from:
| File | What it feeds |
|---|---|
services.ts |
The Services page, one page per service, and the services list on Home (all of them, numbered 01, 02, … in the file’s order) |
lanes.ts |
The lanes on each service page (the ones the service names in lanes.items) and the “New Lane” card in the Home hero (the first lane) |
posts.ts |
The Blog (six at a time as you scroll), one page per post, Home (the first three) and “Other Posts” at the end of a post (up to three of the same category) |
testimonials.ts |
The testimonials on Home (all of them) |
clients.ts |
The logo ticker on Home and About (all of them) and the four names in the Home hero (the first four) |
legal.ts |
One page per legal text: /legal/privacy-policy, /legal/terms-conditions, /legal/cookie-policy |
The order of the items in the file is the order on the site. The Blog doesn’t sort posts by date either: put a new post first to show it first.
Adding a service
Section titled “Adding a service”Copy an existing entry, paste it below, and change the values:
{ slug: "rail-freight", // the URL: /services/rail-freight title: "Rail Freight", summary: "Cost-efficient rail transport…", // the service lists, the top of its page, its search description image: "/images/service-rail-freight.jpg", // the top of its page, the Home list and Services (about 2400 × 1600) about: { title: "Reliable Rail Across Europe.", text: "…", facts: [{ value: "40+", label: "Rail Terminals" }, …], // four figures in white cards }, benefits: { title: "Rail Freight for Every Load.", items: [{ title: "Block Trains", description: "…" }, …], // four key benefits }, lanes: { title: "Connected Across the Continent.", text: "…", items: ["ningbo-hamburg", "singapore-rotterdam"], // slugs from lanes.ts, shown in this order },}A service page shows its name and summary above its photo, then about, benefits (beside the photo set in
service.ts) and its lanes. The titles of the key benefits are also the bullet list under “Key Benefits” on the
Services page.
Two lists elsewhere name the services and don’t follow the collection: the footer’s Services column
(footer.services.links in site.ts) and the quote form’s shipping methods (quoteForm.fields.method.options).
Adding a lane, post, testimonial, client or legal page
Section titled “Adding a lane, post, testimonial, client or legal page”| Add | Fields |
|---|---|
| Lane | slug, title ("Jebel Ali → Rotterdam"), departure and arrival (the ports), transit (the range on the card, "22–28 Days"), average (the Home hero card, "24 Days"), frequency ("Weekly"), description (kept from the original design; no section shows it), image (about 800 × 533). Then add its slug to the lanes.items of the services that use it. |
| Post | slug, title, excerpt (the card text and the search description), image (about 2400 × 1600), category (any words; posts with the same one are listed under each other as “Other Posts”), date ("2026-08-26", shown as “Aug 26, 2026”), body (rich text) |
| Testimonial | slug, title (the quote’s headline), quote, name, role, company, photo (square, about 800 × 800) and rating (out of 5: 5 shows “5.0/5” and five stars) |
| Client | slug, name (also the logo’s text for screen readers) and logo: an SVG file in public/images/, shown 16 px tall at its own width |
| Legal page | slug (the URL, /legal/<slug>), title, updated ("2026-09-02", shown as “Last Updated: Sep 2, 2026”) and body (rich text). Link it from footer.legal in site.ts. |
A post’s search description is its excerpt, a service’s its summary and a legal page’s its first paragraph, cut at 160 characters.
Removing an item
Section titled “Removing an item”Delete the entry. Its page, its card and its sitemap entry disappear on the next build. A service names its lanes by
slug: when you delete a lane, take its slug out of the services too (a slug that matches no lane is skipped). Links
written out in site.ts (the footer’s Services column, the legal links) stay until you remove them.
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.
Rich text: posts and legal pages
Section titled “Rich text: posts and legal pages”A post body or a legal text is a list of blocks:
body: [ { type: "heading", text: "Information We Collect" }, // a heading { type: "heading", level: 3, text: "Information You Provide" }, // a smaller heading { type: "paragraph", text: "A plain paragraph." }, { type: "paragraph", highlight: "Bold start:", text: " and the rest of the paragraph." }, { type: "list", items: [ // bullets; ordered: true for numbers [{ type: "paragraph", text: "First item" }], [{ type: "paragraph", highlight: "Second:", text: " with a bold start" }], ] },]Each list item is itself a list of blocks, so a numbered item can hold paragraphs and a nested list. Text is plain: the
bold parts are highlight, not **stars**. The demo’s posts are paragraphs only; the legal pages use headings at both
levels.
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 large as the demo’s, which the placeholders show:
| Photos | Demo size |
|---|---|
| Home hero (also behind the 404 page), the photo band on Home, the About photo, the call to action, service and post photos | 2400 px wide |
| The Contact cover | 2400 × 3600, portrait |
| “Who we are” on About (also next to the key benefits on every service page) | 1200 × 1600, portrait |
| “Why Choose Us” on Home (the first also beside the quote form) | 1200 × 773 and 600 × 400 |
| Industries | 1200 × 814 for the wide first photo, 600 px wide for the others |
| Lanes, steps, the help card next to the services | 800 px wide |
| Testimonial portraits | 800 × 800 |
| James Carter (Home quote, About) and Sarah Mitchell (the help card) | 600 × 600 and 200 × 200 |
Keep the demo’s aspect ratios, because the layout crops to fit. A photo used in two places changes in both when you replace the file; to show different photos, give one of them another path in the content.
Two things sit outside the content because browsers and social networks ask for them by name:
| File | What it is |
|---|---|
src/app/icon.svg, src/app/apple-icon.png |
The icon in the browser tab and on a phone’s home screen |
public/opengraph-image.png |
The picture shown when someone shares a link (2400 × 1260; 1200 × 630 or larger) |
Its description for screen readers is shareImage.alt in src/lib/meta.ts. Every page uses this image when shared,
except the service and post pages, which share their own photo.
Text that is not in content/
Section titled “Text that is not in content/”Almost every word is content, including the form’s messages (quoteForm in site.ts). The few interface words that
never change per site live in the code:
- “Menu” (the phone menu button’s label for screen readers) and “Main” (the menu’s name) in
src/design-system/, and “Phone” (the phone menu’s name) insrc/components/site/Header.tsx; - “Clients” (the name of the logo ticker for screen readers) in
src/components/sections/ClientsSection.tsx; - “/5” after a testimonial’s rating in
src/components/sections/TestimonialsSection.tsx; - the date format of posts and legal pages (“Aug 26, 2026”) in
src/lib/format.ts.
Search for the word and you will find it.
After editing
Section titled “After editing”npm run buildA successful build means every content file has the fields it needs and every page still renders. It doesn’t open
the images or the links written as text ("/contact"): click through the site once with npm start after big changes.
See Going live for the rest of the checklist.