Skip to content
Sign inJoin waitlist

Pages and sections — Ciketo Astro

A page is a small file that picks sections and hands them content. src/pages/blog.astro is the whole Blog page:

---
import BlogListSection from "../components/sections/BlogListSection.astro";
import CtaSection from "../components/sections/CtaSection.astro";
import blogPage from "../content/pages/blog.json";
import siteContent from "../content/site.json";
import Layout from "../layouts/Layout.astro";
import { getPosts } from "../lib/content";
import { toPostCard } from "../lib/to-ui";
const posts = await getPosts();
---
<Layout title={blogPage.meta.title} description={blogPage.meta.description}>
<BlogListSection label={blogPage.label} title={blogPage.title} loading={blogPage.loading} posts={posts.map(toPostCard)} />
<CtaSection {...siteContent.cta} />
</Layout>
  • Layout gives the page its browser title, description, canonical link, share image, header and footer.
  • getPosts() reads the collection (see Editing the content). toPostCard turns each post into what the card shows (src/lib/to-ui.ts).
  • The sections render them; CtaSection takes the call to action from src/content/site.json.

In src/components/sections/, one file per section. Each takes its copy from a page file (or site.json) and its items from a collection.

Section Used on
HomeHeroSection, HomeAboutSection, HomeServicesSection, ImageBand, TestimonialsSection, HomeBlogSection, FaqSection Home
AboutHeroSection, AboutStorySection, LeaderSection About
ClientsSection, IndustriesSection Home, About
ServicesListSection Services
ServiceHeroSection, ServiceIntroSection, ServiceBenefitsSection, ServiceLanesSection Service
HowItWorksSection Home, Services, Service
QuoteFormSection Home, Service
CtaSection Home, About, Services, Blog
BlogListSection Blog
PostArticleSection, RelatedPostsSection Blog post
ContactSection Contact
LegalSection The legal pages
NotFoundSection 404

“How it works”, the industries, the client intro, the call to action and the quote form have the same copy wherever they appear (howItWorks, industries, clientsIntro, cta and quoteForm in src/content/site.json), so changing it once changes it everywhere.

QuoteForm.astro is the form itself: QuoteFormSection puts it on a white card beside a photo (Home, Service), and ContactSection beside the address and the business hours. AboutHeroSection is the title block and the wide photo under it.

Every page type with each section outlined and labelled: the component that renders it, the file to edit, and where its copy (src/content/pages/*.json, src/content/site.json) and items (src/content/collections/*.json) come from. Header and footer take their links and details from src/content/site.json. Photos are the placeholders of the download.

The hero’s lane card is the first lane in lanes.json and its four names the first four clients in clients.json; the services list shows every service, and the blog the first three posts.

Home: sections and the files behind them

The leader’s message is leader in src/content/pages/about.json; the facts, the industries and the call to action come from site.json.

About: sections and the files behind them

Each row’s “Key Benefits” are the titles of the service’s benefits.items.

Services: sections and the files behind them

The title, photo, the block under it, the key benefits and the lanes come from the service in services.json (its lanes from lanes.json, by slug); the labels and the photo beside the benefits from src/content/pages/service.json.

Service: sections and the files behind them

Every post is in the page; the list shows six and adds six more each time the spinner under it scrolls into view.

Blog: sections and the files behind them

The label above the title is the post’s category. “Other Posts” lists up to three posts of the same category, and is left out when there are none.

Blog post: sections and the files behind them

The address, phone and e-mail come from contact in site.json, the business hours from src/content/pages/contact.json, the form from quoteForm.

Contact: sections and the files behind them

One page per entry in legal.json: its title, its date (updated) and its text.

A legal page: sections and the files behind them

Page not found: sections and the files behind them

Move the lines in the page file, or delete one. To take the FAQ off the home page, delete <FaqSection … /> from src/pages/index.astro (and its import line); its copy in src/content/pages/home.json can stay or go.

  1. Add the URL to src/content/routes.ts:

    careers: "/careers",
  2. Add its copy to src/content/pages/careers.json, with a meta (title, description):

    {
    "meta": { "title": "Careers", "description": "Join the Ciketo team: open roles in freight forwarding, operations and customer service across our network." },
    "label": "Careers",
    "title": "Move the world's cargo with us",
    "text": "We're hiring planners, forwarders and customer service specialists in our offices and ports."
    }
  3. Create src/pages/careers.astro:

    ---
    import CtaSection from "../components/sections/CtaSection.astro";
    import careersPage from "../content/pages/careers.json";
    import siteContent from "../content/site.json";
    import Section from "../design-system/components/layout/Section.astro";
    import SectionTitle from "../design-system/components/layout/SectionTitle.astro";
    import Layout from "../layouts/Layout.astro";
    ---
    <Layout title={careersPage.meta.title} description={careersPage.meta.description}>
    <Section>
    <SectionTitle as="h1" label={careersPage.label} title={careersPage.title} text={careersPage.text} leadClass="max-w-[450px]" />
    </Section>
    <CtaSection {...siteContent.cta} />
    </Layout>
  4. Link to it: add { "label": "Careers", "href": "/careers" } to navigation in src/content/site.json, or to the footer’s footer.company.links.

  5. Add it to src/pages/sitemap.xml.ts, next to the other top-level pages (routes.careers in the pages list).

A page that should open with a full-width dark photo under a transparent header, like Home and Contact, passes cover to Layout and puts data-header-cover on its first section (see HomeHeroSection.astro).

Delete its file under src/pages/, its entry in navigation, in the footer’s links and in src/pages/sitemap.xml.ts, and the route in routes.ts. npm run check then tells you about anything still pointing at it through routes. Buttons in the content link with plain paths ("href": "/contact"): search the content for the path too.

src/pages/blog/[slug].astro builds one page per post:

export const getStaticPaths = (async () => {
return (await getPosts()).map((post) => ({ params: { slug: post.slug }, props: { post } }));
}) satisfies GetStaticPaths;

Add a post to src/content/collections/posts.json, and its page, its links and its sitemap entry appear on the next build; any other slug is a 404. The same pattern builds the service pages (src/pages/services/[slug].astro) and the legal pages (src/pages/legal/[slug].astro).

src/pages/404.astro, with its copy in src/content/pages/not-found.json. It is noindex, like the style guide. Static hosts serve 404.html for any unknown address.

  • Sitemap: src/pages/sitemap.xml.ts builds sitemap.xml from routes.ts and the collections: the five main pages, every service, every post (with its date) and every legal page (with its updated date), so new items list themselves. The 404 page and the style guide are left out.
  • Robots: src/pages/robots.txt.ts builds robots.txt and points at the sitemap. Both use site.url, so set your domain before publishing.
  • Per page: every indexable page gets a title, a description, a canonical link, an og:url and a share image from src/layouts/Layout.astro. A title that would be longer than 60 characters with | Ciketo appended is shown without the suffix. The home page’s title is site.title from src/content/site.json, as it is.
  • Descriptions: the meta.description of About, Services, Blog and Contact; a service’s summary; a post’s excerpt; a legal page’s first paragraph; site.description for Home and any page without one. Those taken from a service, a post or a legal page are cut at 160 characters with “…”.
  • Posts are articles for search engines and share cards (og:type article with their date), and services and posts share their own photo.
  • Not indexed: the style guide and the 404 page (noindex).