# Beste UI

> Beautiful, accessible blocks, pieces and components for shadcn/ui and Tailwind CSS, built for React and Next.js. Install one with the shadcn CLI and the code is yours to edit: no runtime dependency, nothing to upgrade.

Markdown rendition of https://ui.beste.co/block/blog61. Every page on the site has one: add `.md` to any address, or send `Accept: text/markdown`.

Last updated: 2026-08-03

Whole catalog for LLMs: https://ui.beste.co/llms.txt. Registry index: https://ui.beste.co/r/registry.json

---
1. /
2. [Blocks](/blocks)
3. /
4. [Blog](/blocks/blog)
5. /
6. Filterable Archive Index

# Filterable Archive IndexFREE

A dense blog archive whose subject pills are derived from the posts themselves and carry live counts, filtering a two-column list of hairline rows stamped with a date and a reading time.

ViewCodeDocs

Base UI

![](https://oud.pics/sm/l/npm.svg)`npx shadcn add https://ui.beste.co/r-base/blog61`

## Blog61: Filterable Archive Index

A dense blog archive whose subject pills are derived from the posts themselves and carry live counts, filtering a two-column list of hairline rows stamped with a date and a reading time.

Free block

This block is free. No license or account is required: install it with the CLI and use it in unlimited projects.

### Installation

**Radix flavor**

bashCopy

```
npx shadcn add "https://ui.beste.co/r/blog61"
```

**Base UI flavor**

bashCopy

```
npx shadcn add "https://ui.beste.co/r-base/blog61"
```

This installs the block to `components/beste/block/blog61.tsx` plus the `badge23` component it uses for the eyebrow.

### Quick start

The installed file exports `blog61Demo` alongside the block: the exact props behind the preview above. Spread it to get a working archive in one line.

tsxCopy

```
import { Blog61, blog61Demo } from "@/components/beste/block/blog61";

export default function ArchivePage() {
  return <Blog61 {...blog61Demo} />;
}
```

Then replace the demo with your own props. Written out, a trimmed setup looks like this:

tsxCopy

```
import { Blog61 } from "@/components/beste/block/blog61";

export default function ArchivePage() {
  return (
    <Blog61
      badge={{ label: "Archive" }}
      heading="Everything we have written, by subject"
      description="No infinite scroll and no recommended reading."
      allLabel="Everything"
      posts={[
        {
          date: "12 May 2026",
          topic: "Operations",
          title: "The waiting list is a scheduling problem, not a queue",
          readingTime: "6 min",
          href: "/blog/waiting-list",
        },
        {
          date: "28 Apr 2026",
          topic: "Billing",
          title: "Why we raise the invoice from the appointment, not the month",
          readingTime: "8 min",
          href: "/blog/invoicing",
        },
      ]}
      emptyLabel="Nothing filed under that yet."
    />
  );
}
```

### Props

| Prop        | Type              | Default | Description                                               |
| ----------- | ----------------- | ------- | --------------------------------------------------------- |
| badge       | { label: string } | –       | Eyebrow above the hairline rule, rendered through Badge23 |
| heading     | string            | –       | Section heading in the left column of the header          |
| description | string            | –       | Supporting paragraph, right-aligned from md up            |
| allLabel    | string            | "All"   | Label for the unfiltered pill                             |
| posts       | ArchivePost\[\]   | \[\]    | The archive itself, in the order it should read           |
| emptyLabel  | string            | –       | Line shown when a filter matches nothing                  |
| className   | string            | –       | Extra classes for the outer section                       |

tsCopy

```
type ArchivePost = {
  date: string;
  topic: string;
  title: string;
  readingTime: string;
  href: string;
};
```

### Behavior notes

* The filter pills are derived, not configured. Topics come from `Array.from(new Set(posts.map(post => post.topic)))`, so adding a post with a new `topic` adds a pill automatically, in first-appearance order.
* Counts are computed the same way, per render, so they always match what the filter will actually show.
* The active filter is one piece of state holding either a topic string or `null`, with `null` meaning unfiltered. The all-pill carries `value: null`, so it is the same control rather than a special case.
* Posts are never sorted by the block. The array order is the display order, so pass them in the order you want them read.
* Rows are whole `Link` elements laid out as a two-column grid, filling column by column, so a filtered list reflows into the same two columns rather than leaving one empty.
* `emptyLabel` only renders when the current filter matches nothing, which can only happen if `posts` is empty, since every pill is derived from a post that exists.
* The pills are real `button` elements with `aria-pressed`, and carry `cursor-pointer` explicitly, since Tailwind v4 buttons default to `cursor: default`.

## More Blog blocks

[View all Blog](/blocks/blog)

[](/block/blog58)

PRO

blog58

### Ruled Writing Index

Image-free article index where every entry is one ruled row carrying the date, the category, the title and the reading time with a corner arrow, stacking to a readable block on mobile.

[](/block/blog18)

PRO

blog18

### Month-Grouped Archive

Blog archive organized by month with compact list entries. Small thumbnails and formatted dates create a scannable chronological view.

[](/block/blog8)

PRO

blog8

### Category Tabs Filter

Filterable blog grid with tab navigation for categories. Posts automatically filter by category selection with smooth content switching.

[](/block/blog44)

PRO

blog44

### Newsroom Lead and Index

A newsroom listing with a heading, a divider, and an eyebrow over a hairline rule, a two-column lead story with a large image, the remaining stories stacked as numbered ruled rows with square thumbnails, and a seal button to the full archive.

[](/block/blog43)

PRO

blog43

### Editorial Article Grid

A blog listing with an eyebrow over a hairline rule, a two-column heading, and three linked article cards with a hover-zoom image, a category label, a title, an excerpt, and byline.

[](/block/blog11)

PRO

blog11

### Compact Thumbnail List

Two-column compact blog list with small square thumbnails. Space-efficient design showing many posts at once with minimal metadata.

## Ship the interface, keep the code.

New blocks, pieces and components every week. Install one with a command and it is yours to edit. No runtime dependency, no upgrade path to fight.

[Browse the libraryBrowse the library](/blocks)[See pricingSee pricing](/pricing)

### Library

* [Blocks](/blocks)
* [Pages](/pages)
* [Pieces](/pieces)
* [Components](/components)
* [Search](/search)

### Learn

* [Docs](/docs)
* [AI & MCP](/docs/mcp)
* [Blog](/blog)
* [Free tools](/tools)
* [What's new?](/changelog)
* [Website Builder](https://beste.co)

### More

* [Pricing](/pricing)
* [Referrals](/referrals)
* [License](/license)
* [GitHub](https://github.com/beste-co/beste-ui)

### Shadcn Blocks

* [Shadcn Hero Blocks](/blocks/hero)
* [Shadcn Feature Blocks](/blocks/feature)
* [Shadcn Pricing Blocks](/blocks/pricing)
* [Shadcn CTA Blocks](/blocks/cta)
* [Shadcn FAQ Blocks](/blocks/faq)
* [Shadcn About Blocks](/blocks/about)
* [Shadcn Stats Blocks](/blocks/stats)
* [Shadcn Footer Blocks](/blocks/footer)
* [Shadcn Navigation Blocks](/blocks/navigation)
* [Shadcn Auth Blocks](/blocks/auth)
* [Shadcn Ecommerce Blocks](/blocks/ecommerce)
* [Shadcn Portfolio Blocks](/blocks/portfolio)
* [Shadcn Showcase Blocks](/blocks/showcase)
* [Shadcn Careers Blocks](/blocks/careers)
* [Shadcn Onboarding Blocks](/blocks/onboarding)
* [Shadcn Coming Soon Blocks](/blocks/coming-soon)
* [Shadcn Post Blocks](/blocks/post)
* [Shadcn Legal Blocks](/blocks/legal)
* [Shadcn Workflow Blocks](/blocks/workflow)
* [Shadcn News Blocks](/blocks/news)

© 2026, [Beste](https://beste.co). All rights reserved.