• Features
  • Pricing
Get Started

Editorial FeedLaunch JournalEngineering NotesCommunity Stories
Shadcn Registry

Engineering Notes

A Paragraph CMS-native technical blog layout with search, filters, a featured post, and archive rows.

Engineering Notes renders a technical blog listing with a featured post, search, category popover, archive rows, RSS action, empty states, and load-more pagination.

Installation

pnpm dlx shadcn@latest add paragraphcms/shadcn-registry/engineering-notes
npx shadcn@latest add paragraphcms/shadcn-registry/engineering-notes
yarn dlx shadcn@latest add paragraphcms/shadcn-registry/engineering-notes
bunx --bun shadcn@latest add paragraphcms/shadcn-registry/engineering-notes

Install the runtime dependencies:

pnpm add @paragraphcms/client @tabler/icons-react clsx tailwind-merge @base-ui/react class-variance-authority
npm install @paragraphcms/client @tabler/icons-react clsx tailwind-merge @base-ui/react class-variance-authority
yarn add @paragraphcms/client @tabler/icons-react clsx tailwind-merge @base-ui/react class-variance-authority
bun add @paragraphcms/client @tabler/icons-react clsx tailwind-merge @base-ui/react class-variance-authority

Add these registry files to your project:

  • ui/engineering-notes.tsx
  • ui/aspect-ratio.tsx
  • ui/badge.tsx
  • ui/button.tsx
  • ui/input.tsx
  • ui/popover.tsx
  • lib/utils.ts

Keep the aliases aligned with your components.json: @/components/ui/* and @/lib/utils.

Prerequisites

You need a Paragraph CMS API key available only on the server:

.env
PARAGRAPH_API_KEY=your_api_key

Create a server-side Paragraph CMS client:

paragraph.config.ts
import { Client } from "@paragraphcms/client";

const apiKey = process.env.PARAGRAPH_API_KEY;

if (!apiKey) {
  throw new Error("PARAGRAPH_API_KEY environment variable is not set");
}

export const client = new Client({ apiKey });

Engineering Notes expects PageSummaryWithSlug[]. It reads labels from post.labels, author metadata from post.author, and summaries from post.fields.excerpt or post.fields.summary.

Usage

Fetch posts from Paragraph CMS, pass the first item as featured_post, and render the remaining posts as the archive.

app/blog/page.tsx
import { EngineeringNotes } from "@/components/ui/engineering-notes";
import { client } from "@/paragraph.config";

export default async function BlogPage() {
  const { data: posts, error } = await client.pages.list({
    collection: "engineering",
    requiredSlug: true,
  });

  if (error) {
    throw error;
  }

  return (
    <EngineeringNotes
      base_path="/blog"
      featured_post={posts[0] ?? null}
      posts={posts.slice(1)}
      rss_href="/blog/rss.xml"
      title="Engineering"
    />
  );
}

If you omit categories, the component builds its filter menu from the labels present on the fetched posts.

Launch Journal

A Paragraph CMS-native launch feed with featured posts, labels, search, authors, and pagination.

Community Stories

A Paragraph CMS-native editorial grid for lightweight story cards.

On this page

InstallationPrerequisitesUsage