# Blog Page

> A whole blog index, built from our website components: a floating navbar, a page title, every post with the newest drawn wide and a row of tags to narrow them, a closing band, and a footer.

- Name: `blog-page`
- Status: beta
- Categories: blog, posts, marketing, page
- Files: the install writes `blog-page.tsx`, and any part files named `blog-page-*.tsx`, to your `components` alias, `@/components` by default. Edit them freely. They are yours.
- Other registry items: `@arbokui/navbar`, `@arbokui/headline`, `@arbokui/post-grid`, `@arbokui/call-to-action-band`, `@arbokui/footer`. The install adds them.
- Gallery: https://arbokui.com/templates/blog-page
- Registry item: https://arbokui.com/r/blog-page.json

## Install

1. Add the registry to `components.json`. Do this first, once:

   ```bash
   npx shadcn@latest registry add "@arbokui=https://arbokui.com/r/{name}.json"
   ```

   The command writes this entry. You can also add it by hand:

   ```json
   {
     "registries": {
       "@arbokui": "https://arbokui.com/r/{name}.json"
     }
   }
   ```

   Without this step, the shadcn CLI looks up `@arbokui` in a public list that Arbokui does not control.

2. Add the theme once per app. It replaces your color tokens with ones checked for contrast:

   ```bash
   npx shadcn@latest add @arbokui/theme
   ```

3. Add the template. It also adds every component it uses:

   ```bash
   npx shadcn@latest add @arbokui/blog-page
   ```

## Use it for

- The list of posts on a product site's blog. Render it as the whole page, from your app's page file.
- Write every word in the props: one object for the navbar, the header, the posts, the closing band, and the footer.
- Pass the posts newest first, each with an \`href\` to its own page. Post Page draws that page.
- Give each post one \`tag\`, so the row of tags can narrow the list. Set \`posts.filter\` to false to hide the row.
- Pick a post count that fills the rows: the newest drawn wide, then rows of three, like 7 or 10.
- Pass your router's link once in \`renderLink\`. The navbar, the posts, the closing band, and the footer all use it. From a server page, render the page from a client file, since a server page cannot pass a function.
- Set \`embedded\` when you show the page inside another page, like a gallery, so it has no second main.

## Avoid it for

- Hundreds of posts on one page. Show the newest, and split the rest across pages.
- A tag on only one post. Each tag should narrow the list to a few.

## Props

- `navbar`: `NavbarProps`. The Navbar's props. It floats as a pill once the page scrolls, and folds into a menu below 42rem.
- `header`: `HeadlineProps`. The headline at the top of the page. It renders as the page's one h1.
- `posts`: `PostGridProps`. Required. Post Grid's props, like \`posts\`. \`featured\` and \`filter\` default to true here. Each post's title is an h2, right under the page's h1.
- `cta`: `CallToActionBandProps`. The closing band above the footer.
- `footer`: `FooterProps`. The Footer's props.
- `renderLink`: `(props: NavbarLinkProps) => ReactNode`. Default `a plain <a>`. Draws every link in the navbar, the posts, the closing band, and the footer, unless a part sets its own.
- `embedded`: `boolean`. Default `false`. Renders the content in a div, not a main, for a preview inside another page.
- `className`: `string`. Extra classes on the root, which holds the container query.

## Accessibility

- The content sits in a main landmark, between the navbar's nav and the footer, so skip links and screen readers find it.
- The header renders the page's one h1, and each post's title is an h2 under it.
- Each part keeps its own accessibility, listed on its page.

## Examples

### A short blog index

```tsx
<BlogPage
  navbar={{ brand: "Workspace", links: [{ href: "/blog", label: "Blog", current: true }] }}
  header={{ title: "The blog.", muted: "What we ship, and how we work." }}
  posts={{
    posts: [
      { href: "/blog/shared-folders", title: "Shared folders are here", tag: "Product", date: "2026-10-28" },
      { href: "/blog/plan-a-release", title: "How to plan a release", tag: "Guides", date: "2026-10-12" },
    ],
  }}
  footer={{
    brand: "Workspace",
    columns: [{ title: "Company", links: [{ href: "/blog", label: "Blog" }] }],
    legal: "© 2026 Workspace",
  }}
/>
```
