Blog

Three-Card Blog Grid

Centred blog section with a heading and intro over a three-column grid of posts. Each card shows cover art, date and author, a linked title and a one-sentence excerpt.

Free, MIT licenseOpen in Browse
import { Heading } from "@/components/editorial/heading"
import {
  Post,
  PostAuthor,
  PostContent,
  PostDate,
  PostExcerpt,
  PostGroup,
  PostMedia,
  PostMeta,
  PostTitle,
} from "@/components/editorial/post"
import {
  Section,
  SectionContent,
  SectionDescription,
  SectionHeader,
  SectionTitleGroup,
} from "@/components/editorial/section"

// The copy: change text here, not in the markup.
const COPY = {
  title: "From the blog",
  body: "Advice from the Orbcore team on running a support desk that stays calm.",
} as const

const POSTS = [
  {
    image: "https://01orbital.dev/art/kit/thomas-v2-596378.png",
    title: "Five rules for a shared inbox",
    description: "What changes when the whole team answers from one queue.",
    datetime: "2026-09-18",
    date: "Sep 18, 2026",
    author: "Mae Jemison",
    href: "#",
  },
  {
    image:
      "https://01orbital.dev/art/kit/swiss-orbital-dot_matrix-teal-687039-lightsoff.png",
    title: "Replies people finish reading",
    description:
      "Short, plain answers that close the conversation the first time around.",
    datetime: "2026-09-12",
    date: "Sep 12, 2026",
    author: "Ellen Ochoa",
    href: "#",
  },
  {
    image: "https://01orbital.dev/art/kit/layered-currents-654353.png",
    title: "What 10,000 surveys taught us",
    description:
      "The two questions that tell you more than a full satisfaction report.",
    datetime: "2026-09-06",
    date: "Sep 6, 2026",
    author: "Chris Hadfield",
    href: "#",
  },
] as const

export default function Blog01() {
  return (
    <Section>
      <SectionHeader align="center">
        <SectionTitleGroup>
          <Heading>{COPY.title}</Heading>
        </SectionTitleGroup>
        <SectionDescription>{COPY.body}</SectionDescription>
      </SectionHeader>
      <SectionContent>
        <PostGroup cols={3}>
          {POSTS.map((post) => (
            <Post key={post.title}>
              <PostMedia>
                <img src={post.image} alt="" loading="lazy" />
              </PostMedia>
              <PostContent>
                <PostMeta>
                  <PostDate dateTime={post.datetime}>{post.date}</PostDate>
                  <PostAuthor>{post.author}</PostAuthor>
                </PostMeta>
                <PostTitle>
                  <a href={post.href}>{post.title}</a>
                </PostTitle>
                <PostExcerpt>{post.description}</PostExcerpt>
              </PostContent>
            </Post>
          ))}
        </PostGroup>
      </SectionContent>
    </Section>
  )
}

Installation

pnpm dlx shadcn add @01orbital/blog-01
npx shadcn add @01orbital/blog-01
yarn shadcn add @01orbital/blog-01
bunx --bun shadcn add @01orbital/blog-01

Free under the MIT license. Add the @01orbital registry to components.json once (install guide), then run the command.

It lands at components/blocks/blog/blog-01/index.tsx, as source you own and edit.

Usage

import Blog01 from "@/components/blocks/blog/blog-01"

export default function Example() {
  return <Blog01 />
}

Dependencies

Registry pieces it installs with it: