---
title: "Build layout and pages"
description: "Configure the shared Header and Footer, then publish pages through SysthemaPage."
requested_language: sk
language: en
translation_notice: "This page isn't translated yet"
url: https://docs.systhema.app/sk/next/guides/build-a-site/layout-and-pages
version: unreleased (main)
docs_index: https://docs.systhema.app/sk/next/llms.txt
---
> This page isn't translated yet. Showing English.


## Goal

Create shared navigation and publish the home, services, about, contact and privacy pages. Use the starter's CMS route and default page template first.

## 1. Keep shared chrome in the site template

The starter uses `RootLayout`, `RootHeader` and `RootFooter`. The latter two render the Header and Footer globals with Systhema's components. Replace the logo and configure their content in Admin.

This replacement preserves the starter's responsive menu controls. For a localized site, make the same edits in `shell.tsx` and pass its route locale to `RootLayout`; do not force English.

```tsx title="src/app/(site)/template.tsx"
import type { ReactNode } from 'react'
import { Geist } from 'next/font/google'
import configPromise from '@payload-config'
import { getPayload } from 'payload'
import { RootLayout, RootHeader, RootFooter } from '@systhemaui/payload/next'
import './globals.css'

const geist = Geist({ subsets: ['latin'], weight: ['400', '700'] })

function Logo() {
  return <span>Northline</span>
}

export default function SiteTemplate({ children }: { children: ReactNode }) {
  const payloadInstance = getPayload({ config: configPromise })

  return (
    <RootLayout
      className={geist.className}
      htmlAttributes={{ lang: 'en' }}
      payloadInstance={payloadInstance}
    >
      <RootHeader
        payloadInstance={payloadInstance}
        position="sticky"
        logo={<Logo />}
        elementProps={{
          headerNavigationItem: { className: 'max-lg:hidden' },
          headerMenuToggle: { className: 'lg:hidden' },
          headerCta: { className: 'max-lg:hidden' },
          menu: { className: 'lg:hidden' },
          menuBackdrop: { className: 'lg:hidden' },
        }}
      />
      {children}
      <RootFooter payloadInstance={payloadInstance} logo={<Logo />} />
    </RootLayout>
  )
}
```

See [Header](https://docs.systhema.app/sk/next/components/header.md), [Footer](https://docs.systhema.app/sk/next/components/footer.md) and [Header and Footer content](https://docs.systhema.app/sk/next/payload/content/header-and-footer.md).

## 2. Create the CMS pages

In Admin, create Home, Services, About, Contact and Privacy in Pages. Add a Cookie Policy page if the site requires one. Use the default template. Select the home page in General Settings. Build navigation using internal page references so routing can resolve the correct paths.

Publish each page after adding a title and initial content. Draft pages are for preview; verify published URLs while signed out.

## 3. Let SysthemaPage own CMS routing

The managed catch-all already imports and renders this API:

```tsx title="Managed CMS catch-all, shown for reference"
import configPromise from '@payload-config'
import { getPayload } from 'payload'
import { SysthemaPage } from '@systhemaui/payload/next'

export default async function Page({
  params,
  searchParams,
}: {
  params: Promise<{ segments?: string[] }>
  searchParams: Promise<Record<string, string | string[] | undefined>>
}) {
  return (
    <SysthemaPage
      params={params}
      searchParams={searchParams}
      payloadInstance={getPayload({ config: configPromise })}
    />
  )
}
```

Do not replace that route to implement a custom CMS page. Register a page template instead. `SysthemaPage` resolves the page, chooses its template and connects live preview. The catch-all's separate `generateMetadata` export calls `generateSysthemaMetadata`; retain it. See [Frontend rendering](https://docs.systhema.app/sk/next/payload/frontend/rendering.md).

The default template owns `<main id="main-content">` and `<Article>`. Its root content field accepts section-level blocks. Do not add another main or Article inside those blocks.

## 4. Add a code-owned route only when needed

A route outside `(systhema)` can serve a page whose content is genuinely code-owned:

```tsx title="src/app/(site)/status/page.tsx"
import { Article, Section, Heading, Paragraph } from '@systhemaui/next'

export default function StatusPage() {
  return (
    <main id="main-content">
      <Article theme="default" layoutBackground="main">
        <Section>
          <Heading.h1>Service status</Heading.h1>
          <Paragraph>Contact the office for current service availability.</Paragraph>
        </Section>
      </Article>
    </main>
  )
}
```

Choose route names that do not hide intended CMS pages. Use a [custom page template](https://docs.systhema.app/sk/next/guides/recipes/custom-page-template.md) when editors need to control the content.

## Check your work

- The logo, desktop navigation and mobile menu work.
- The skip link lands on `main-content`.
- Published pages load while signed out, including nested paths.
- Footer links point to the right pages.

Next: [Choose the content model](content-model.md).
