NS Design System
v3.0.0 · 257 tokens

110Blog index

The index: one featured post, a grid of the rest, and a rail carrying categories, an archive and the newsletter form. There is no masonry variant on purpose — a masonry index puts the second post below the fold to make the first one taller, which is a layout serving itself rather than the reader.

Use it for

  • The blog home
  • A category or tag archive, with the featured card dropped
  • An author's post list

Not for

  • Infinite scroll without a real Pagination fallback — a footer nobody can reach is a footer that does not exist

Index with rail

Architecture

The data model is the product

Every automation problem I have been called in to fix was a schema problem wearing a costume. Here is how to tell the difference before you write a line of Apex.

markup
<div class="ns-blog-listing" style="padding:var(--space-6)">
  <div>
    <article class="ns-card ns-bcard ns-bcard--wide" style="margin-block-end:var(--space-8)">
      <span class="ns-bcard__cover">
        <span class="ns-ph" aria-hidden="true"></span>
        <span class="ns-tag ns-bcard__cat">Architecture</span>
      </span>
      <div class="ns-card__body">
        <a class="ns-card__link" href="#"><h2 class="ns-bcard__title">The data model is the product</h2></a>
        <p class="ns-bcard__excerpt">Every automation problem I have been called in to fix was a schema problem wearing a costume. Here is how to tell the difference before you write a line of Apex.</p>
        <div class="ns-postmeta">
          <span><img class="ns-postmeta__avatar" src="../assets/logo/favicon.svg" alt=""><span class="ns-postmeta__author">Swarnil Singhai</span></span>
          <span><time datetime="2026-07-28">28 Jul 2026</time></span>
          <span>12 min read</span>
        </div>
      </div>
    </article>

    <div class="ns-blog-grid">
      <article class="ns-card ns-bcard">
        <span class="ns-bcard__cover"><span class="ns-card__media ns-ph" aria-hidden="true"></span><span class="ns-tag ns-bcard__cat">Apex</span></span>
        <div class="ns-card__body">
          <a class="ns-card__link" href="#"><h3 class="ns-bcard__title">Why your trigger fails at 201 records</h3></a>
          <p class="ns-bcard__excerpt">Governor limits are per transaction, not per record.</p>
          <div class="ns-postmeta"><span><time datetime="2026-08-04">4 Aug</time></span><span>6 min</span></div>
        </div>
      </article>
      <article class="ns-card ns-bcard">
        <span class="ns-bcard__cover ns-bcard__cover--empty" aria-hidden="true"><i class="ph ph-article"></i></span>
        <div class="ns-card__body">
          <a class="ns-card__link" href="#"><h3 class="ns-bcard__title">Notes on naming things</h3></a>
          <p class="ns-bcard__excerpt">A short argument for boring, predictable API names.</p>
          <div class="ns-postmeta"><span><time datetime="2026-06-11">11 Jun</time></span><span>3 min</span></div>
        </div>
      </article>
    </div>
  </div>

  <aside class="ns-blog-listing__rail">
    <nav aria-label="Categories">
      <p class="ns-toc__title" style="padding-inline:0">Categories</p>
      <div style="display:flex;flex-wrap:wrap;gap:var(--space-2)">
        <a class="ns-tag ns-tag--pill" href="#">Apex <span class="ns-tag__count">24</span></a>
        <a class="ns-tag ns-tag--pill" href="#">Flows <span class="ns-tag__count">18</span></a>
        <a class="ns-tag ns-tag--pill" href="#">SOQL <span class="ns-tag__count">9</span></a>
        <a class="ns-tag ns-tag--pill" href="#">Architecture <span class="ns-tag__count">7</span></a>
      </div>
    </nav>
    <div>
      <p class="ns-toc__title" style="padding-inline:0">Recent</p>
      <div class="ns-blog-archive">
        <a class="ns-blog-archive__row" href="#"><span class="ns-blog-archive__date">04 Aug</span><span class="ns-blog-archive__title">Why your trigger fails at 201</span><span class="ns-blog-archive__read">6m</span></a>
        <a class="ns-blog-archive__row" href="#"><span class="ns-blog-archive__date">28 Jul</span><span class="ns-blog-archive__title">The data model is the product</span><span class="ns-blog-archive__read">12m</span></a>
        <a class="ns-blog-archive__row" href="#"><span class="ns-blog-archive__date">14 Jul</span><span class="ns-blog-archive__title">What the query planner does</span><span class="ns-blog-archive__read">9m</span></a>
      </div>
    </div>
  </aside>
</div>

Archive

The dense, coverless list where the DATE is the index — for a year page or a tag with two hundred entries. Below 48rem the date moves to its own line rather than squeezing the title.

markup
<div class="ns-blog-archive" style="max-inline-size:34rem;inline-size:100%">
  <a class="ns-blog-archive__row" href="#"><span class="ns-blog-archive__date">04 Aug 2026</span><span class="ns-blog-archive__title">Why your trigger fails at 201 records</span><span class="ns-blog-archive__read">6 min</span></a>
  <a class="ns-blog-archive__row" href="#"><span class="ns-blog-archive__date">28 Jul 2026</span><span class="ns-blog-archive__title">The data model is the product</span><span class="ns-blog-archive__read">12 min</span></a>
  <a class="ns-blog-archive__row" href="#"><span class="ns-blog-archive__date">14 Jul 2026</span><span class="ns-blog-archive__title">What the query planner actually does</span><span class="ns-blog-archive__read">9 min</span></a>
  <a class="ns-blog-archive__row" href="#"><span class="ns-blog-archive__date">02 Jul 2026</span><span class="ns-blog-archive__title">Flow or Apex? A decision table</span><span class="ns-blog-archive__read">5 min</span></a>
</div>

Accessibility contract

  • Each card has exactly one stretched link
  • The archive rows put the date first in the DOM, so the list is scannable by date with a screen reader
  • The category rail is a nav with an accessible name