Pages and sections — Titen 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 blog from "../content/pages/blog.json";import Layout from "../layouts/Layout.astro";import { getPosts } from "../lib/content";import { toPostCard } from "../lib/to-ui";
const posts = await getPosts();---
<Layout title={blog.blogPage.meta.title} description={blog.blogPage.meta.description}> <BlogListSection label={blog.blogPage.label} title={blog.blogPage.title} posts={posts.map(toPostCard)} /></Layout>Layoutgives the page its browser title, description, canonical link, share image, header and footer.getPosts()reads the collection (see Editing the content).toPostCardturns each post into what the card shows (src/lib/to-ui.ts).- The section renders them.
The sections you can use
Section titled “The sections you can use”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, HomeProjectsSection, HomeServicesSection, CtaSection, HomeBlogSection |
Home |
AboutHeroSection, BeginningsSection, ApproachSection, VideoSection, TeamSection, AwardsSection |
About |
ProjectsListSection |
Projects |
CategorySection |
Residential, Hospitality, Commercial |
ProjectHeroSection, ProjectStorySection, RelatedProjectsSection |
Project |
ServicesListSection, ProjectsCtaSection |
Services |
ServiceMainSection |
Service |
BlogListSection |
Blog |
PostMainSection, MorePostsSection |
Blog post |
TestimonialsListSection, ServicesOverviewSection |
Testimonials |
ContactMainSection, ContactSalesSection |
Contact |
ContactFormSection |
Projects, the category pages, Service |
NotFoundSection |
404 |
ContactFormSection (“Let’s Work Together”) appears on five kinds of page with the same copy (projectForm in
src/content/site.json), so changing it once changes it everywhere. The dark “Let’s Talk!” block above every footer is
part of the footer (src/components/site/Footer.astro, copy in footer.cta).
ProjectMosaic.astro and ProjectGrid.astro are the two project layouts the sections share: the mosaic of six cards
(Home, Projects) and the three-column grid. project/ holds the parts of the project story.
Page maps
Section titled “Page maps”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) 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 team and the awards are in src/content/pages/about.json (team.members, awards.items).

Projects
Section titled “Projects”
A project category
Section titled “A project category”The page’s title is the category’s name; its projects are the ones whose category is its slug, the first one shown
wide.

Project
Section titled “Project”
Services
Section titled “Services”
Service
Section titled “Service”The title, image, “About the service” and “What’s included” come from the service in services.json; the headings and
the brochure button from src/content/pages/service.json.


Blog post
Section titled “Blog post”
Testimonials
Section titled “Testimonials”
Contact
Section titled “Contact”
Page not found
Section titled “Page not found”
Reordering or removing a section
Section titled “Reordering or removing a section”Move the lines in the page file, or delete one. To take the blog off the home page, delete <HomeBlogSection … /> from
src/pages/index.astro (and its import line); its copy in src/content/pages/home.json can stay or go.
Adding a page
Section titled “Adding a page”-
Add the URL to
src/content/routes.ts:careers: "/careers", -
Add its copy to
src/content/pages/careers.json, with ameta(title, description):{"meta": { "title": "Careers", "description": "Join the Titen studio: open roles in architecture, interiors and project management." },"label": "Careers","title": "Build the future with us"} -
Create
src/pages/careers.astro:---import ContactFormSection from "../components/sections/ContactFormSection.astro";import careersPage from "../content/pages/careers.json";import siteContent from "../content/site.json";import PageTitle from "../design-system/components/layout/PageTitle.astro";import Section from "../design-system/components/layout/Section.astro";import Layout from "../layouts/Layout.astro";const { projectForm } = siteContent;---<Layout title={careersPage.meta.title} description={careersPage.meta.description}><Section><PageTitle label={careersPage.label} title={careersPage.title} /></Section><ContactFormSection {...projectForm} subject="New job application" /></Layout> -
Link to it: add
{ "label": "Careers", "href": "/careers" }tonavigationinsrc/content/site.json, or to the footer’sstudio.links. -
Add it to
src/pages/sitemap.xml.ts, next to the other top-level pages.
Category pages live at the top level (/residential), so a new page must not share its URL with a category’s slug.
Removing a page
Section titled “Removing a page”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.
Pages built from a collection
Section titled “Pages built from a collection”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 project, service and category pages
(src/pages/[category].astro).
The 404 page
Section titled “The 404 page”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.
Search engines
Section titled “Search engines”- Sitemap:
src/pages/sitemap.xml.tsbuildssitemap.xmlfromroutes.tsand the collections, so new items list themselves. The 404 page and the style guide are left out. - Robots:
src/pages/robots.txt.tsbuildsrobots.txtand points at the sitemap. Both usesite.url, so set your domain before publishing. - Per page: every indexable page gets a title, a description, a canonical link, an
og:urland a share image fromsrc/layouts/Layout.astro. A title that would be longer than 60 characters with| Titenappended is shown without the suffix. - Not indexed: the style guide and the 404 page (
noindex).
The header search
Section titled “The header search”“Search projects” in the header looks through the project pages: titles first, then the text of every project. The
list is built in src/layouts/Layout.astro from getProjects() and written into each page, so the search also works on
static hosts. To search posts too, add them to searchItems there with title, href and text.