--- title: Manage header and footer category: Reuse content across pages order: 3 status: published summary: Render shared header and footer entities in the app layout with dedicated PageViewer components. estimatedTime: 6 min keywords: header footer reuse pageviewer --- In this how-to, you'll learn the usual React Bricks pattern for managing a shared header and footer. Instead of embedding them inside every page, you fetch them once in the app layout and render them with dedicated `` components. Docs reference: [Reuse content across pages](https://docs.reactbricks.com/common-tasks/reuse-content-across-pages/) ## Why use dedicated `PageViewer`s Header and footer are layout elements shared by the whole site. For these global fragments, it is usually better not to use embeds inside every page for performance reasons. Instead, render them directly in your layout with: - one `` for the header - one `` for the footer This is the pattern used in the starter projects scaffolded by the CLI. ## Create a page type for layout entities First, create a dedicated entity page type for layout content. ```tsx import { types } from 'react-bricks/rsc' const pageTypes: types.IPageType[] = [ { name: 'layout', pluralName: 'Layout', defaultStatus: types.PageStatus.Published, getDefaultContent: () => [], isEntity: true, allowedBlockTypes: ['header', 'footer'], }, ] export default pageTypes ``` This does 2 things: - `isEntity: true` puts these pages under the `Entities` tab - `allowedBlockTypes` ensures editors only use layout bricks there After that, editors can create 2 entities: - `header` - `footer` The slug names matter because the layout will fetch those pages by slug. ## Minimal `app/[lang]/layout.tsx` example Here is a simplified version of a starter project pattern. ```tsx {23,24,51,53} import { PageViewer, cleanPage, fetchPage, getBricks, register, types, } from 'react-bricks/rsc' import config from '@/react-bricks/config' import '@/app/globals.css' register(config) const getLayoutData = async ( language: string ): Promise<{ header: types.Page | null footer: types.Page | null }> => { const [header, footer] = await Promise.all([ fetchPage({ slug: 'header', language, config }).catch(() => null), fetchPage({ slug: 'footer', language, config }).catch(() => null), ]) return { header, footer } } export default async function Layout({ children, params, }: { children: React.ReactNode params: Promise<{ lang: string }> }) { const { lang } = await params const { header, footer } = await getLayoutData(lang) const bricks = getBricks() const headerOk = header ? cleanPage(header, config.pageTypes || [], bricks) : null const footerOk = footer ? cleanPage(footer, config.pageTypes || [], bricks) : null return ( {headerOk ? : null}
{children}
{footerOk ? : null} ) } ``` ## What this layout does The important parts are: - `fetchPage` loads the `header` and `footer` entities - `cleanPage` removes unknown or disallowed bricks before rendering - `PageViewer` renders each entity - `main={false}` tells React Bricks these viewers are not the main page content The children route is rendered between them: ```tsx
{children}
``` so every page automatically gets the same shared header and footer. ## Why `cleanPage` is important Before rendering a page returned by the API, the starter projects call `cleanPage`. This removes content that should not be rendered, such as bricks that are unknown in the current project or not allowed by the page type configuration. That makes the render path safer and more predictable. ## If your app is not localized This example uses `app/[lang]/layout.tsx`, so it receives a `lang` route param. If your project is not localized, the same idea still applies. You can just fetch with a fixed language, for example: ```tsx fetchPage({ slug: 'header', language: 'en', config }) ``` and place the same logic in your root `app/layout.tsx`. ## Summary For header and footer, the usual React Bricks approach is: 1. store them as entities 2. fetch them in the layout 3. render them with dedicated `` components Use this pattern for global layout fragments. Use embeds instead for reusable content blocks that editors place inside normal pages: [Reuse a fragment (embed)](/how-tos/reuse-content-across-pages/reuse-a-fragment-embed)