NS Design System
v3.0.0 · 257 tokens

88Course hero

The top of a course page, in five versions — because a course page has five honest situations, not because five looked like a good number. All five carry the same parts in the same order (kicker, title, lede, meta strip, actions, media), so the page does not re-teach itself when the art direction changes. The meta strip is where a stranger decides: rating, learners, runtime, level, language, last updated.

Use it for

  • The top of every course detail page
  • --minimal for a course with no good art, which is most of them
  • --console where there are no assets at all — it needs none

Not for

  • A catalog card — that is Course card
  • A marketing page opener — that is Hero, in Sections
  • Carrying the enrol action alone: the buy box repeats it, because a hero scrolls away

Split — the default

Content beside a media card. The workhorse: the preview video has somewhere to live above the fold. Below 64rem the media moves FIRST — on a phone the preview is the strongest argument, and it should not be the fourth thing.

// Course · Developer track

Apex, from zero to first deploy

The platform's own language, taught in the order you actually need it: the data model first, then classes, then the deploy that puts it live.

4.8 (1,240) 8,410 learners 6h 20m 24 lessons English Updated Aug 2026
Preview · 02:14
markup
<section class="ns-chero">
  <div class="ns-chero__inner">
    <div class="ns-chero__grid">
      <div class="ns-chero__body">
        <span class="ns-chero__kicker">// Course · Developer track</span>
        <h1 class="ns-chero__title">Apex, from zero to first deploy</h1>
        <p class="ns-chero__lede">The platform's own language, taught in the order you actually need it: the data model first, then classes, then the deploy that puts it live.</p>
        <div class="ns-chero__meta">
          <span class="ns-rating" data-value="4.8" data-of="5">
            <span class="ns-rating__value">4.8</span>
            <span class="ns-rating__stars" aria-hidden="true"><span><i class="ph ph-star"></i><i class="ph ph-star"></i><i class="ph ph-star"></i><i class="ph ph-star"></i><i class="ph ph-star"></i></span><span class="ns-rating__fill"><i class="ph-fill ph-star"></i><i class="ph-fill ph-star"></i><i class="ph-fill ph-star"></i><i class="ph-fill ph-star"></i><i class="ph-fill ph-star"></i></span></span>
            <span class="ns-rating__count">(1,240)</span>
          </span>
          <span><i class="ph ph-users-three" aria-hidden="true"></i>8,410 learners</span>
          <span><i class="ph ph-clock" aria-hidden="true"></i>6h 20m</span>
          <span><i class="ph ph-list" aria-hidden="true"></i>24 lessons</span>
          <span><i class="ph ph-globe" aria-hidden="true"></i>English</span>
          <span><i class="ph ph-arrows-clockwise" aria-hidden="true"></i>Updated Aug 2026</span>
        </div>
        <div class="ns-chero__actions">
          <a class="ns-btn ns-btn--primary ns-btn--lg" href="#">Enrol — $49</a>
          <a class="ns-btn ns-btn--soft ns-btn--lg" href="#"><i class="ph ph-play" aria-hidden="true"></i> Preview 2 lessons</a>
        </div>
      </div>
      <div class="ns-chero__media">
        <span class="ns-ph" aria-hidden="true"></span>
        <button type="button" class="ns-chero__play" aria-label="Play the course preview"><i class="ph ph-play-circle" aria-hidden="true"></i></button>
        <span class="ns-chero__caption">Preview · 02:14</span>
      </div>
    </div>
  </div>
</section>

Cover

A photographic still behind the content, scrimmed to the brand navy. For a course whose subject is visual. The scrim runs from 92% to 62% across the inline axis, so the text edge is always the dark end whatever the image does.

Bestseller Certificate
// Learning path

The Salesforce admin trail

Six courses in one order, from your first org to a passing score on the ADM-201.

6 courses 24h Certificate on completion
markup
<section class="ns-chero ns-chero--cover">
  <div class="ns-chero__bg"><span class="ns-ph" aria-hidden="true"></span></div>
  <div class="ns-chero__inner">
    <div class="ns-chero__grid">
      <div class="ns-chero__body">
        <div class="ns-chero__badges">
          <span class="ns-tag">Bestseller</span>
          <span class="ns-tag">Certificate</span>
        </div>
        <span class="ns-chero__kicker">// Learning path</span>
        <h1 class="ns-chero__title">The Salesforce admin trail</h1>
        <p class="ns-chero__lede">Six courses in one order, from your first org to a passing score on the ADM-201.</p>
        <div class="ns-chero__meta">
          <span><i class="ph ph-books" aria-hidden="true"></i>6 courses</span>
          <span><i class="ph ph-clock" aria-hidden="true"></i>24h</span>
          <span><i class="ph ph-medal" aria-hidden="true"></i>Certificate on completion</span>
        </div>
        <div class="ns-chero__actions">
          <a class="ns-btn ns-btn--white ns-btn--lg" href="#">Start the trail</a>
          <a class="ns-btn ns-btn--ghost ns-btn--lg" href="#">See the six courses</a>
        </div>
      </div>
    </div>
  </div>
</section>

Video loop

The same as --cover, with a muted looping clip instead of a still. It is decoration with a bandwidth cost, so: muted loop playsinline, a poster that stands alone, and hidden entirely under prefers-reduced-motion — which leaves exactly the cover version, correctly. (The demo below uses the poster; the markup is what ships.)

// Live cohort · starts 14 Sep

Integration patterns, live

Four weeks, four live builds, one recording of each — with the whole cohort in the same room.

4 live sessions 30 seats Thursdays, 19:00 IST
markup
<section class="ns-chero ns-chero--video">
  <div class="ns-chero__bg">
    <video autoplay muted loop playsinline aria-hidden="true">
      <source src="/media/course-loop.mp4" type="video/mp4">
    </video>
  </div>
  <div class="ns-chero__inner">
    <div class="ns-chero__grid">
      <div class="ns-chero__body">
        <span class="ns-chero__kicker">// Live cohort · starts 14 Sep</span>
        <h1 class="ns-chero__title">Integration patterns, live</h1>
        <p class="ns-chero__lede">Four weeks, four live builds, one recording of each — with the whole cohort in the same room.</p>
        <div class="ns-chero__meta">
          <span><i class="ph ph-video-camera" aria-hidden="true"></i>4 live sessions</span>
          <span><i class="ph ph-users-three" aria-hidden="true"></i>30 seats</span>
          <span><i class="ph ph-calendar" aria-hidden="true"></i>Thursdays, 19:00 IST</span>
        </div>
        <div class="ns-chero__actions">
          <a class="ns-btn ns-btn--white ns-btn--lg" href="#">Reserve a seat</a>
          <a class="ns-btn ns-btn--ghost ns-btn--lg" href="#">Syllabus</a>
        </div>
      </div>
    </div>
  </div>
</section>

Minimal

Hairline and type only. For a course with no good art — which is most of them, and a blank grey box is worse than no box. This is the version to reach for when someone asks "what image should go here" and there is no honest answer.

// Course

SOQL, properly

Selective queries, relationship traversal, and the index behaviour that decides whether your report loads or times out.

6 lessons 1h 05m Intermediate
markup
<section class="ns-chero ns-chero--minimal">
  <div class="ns-chero__inner">
    <div class="ns-chero__grid">
      <div class="ns-chero__body">
        <span class="ns-chero__kicker">// Course</span>
        <h1 class="ns-chero__title">SOQL, properly</h1>
        <p class="ns-chero__lede">Selective queries, relationship traversal, and the index behaviour that decides whether your report loads or times out.</p>
        <div class="ns-chero__meta">
          <span><i class="ph ph-list" aria-hidden="true"></i>6 lessons</span>
          <span><i class="ph ph-clock" aria-hidden="true"></i>1h 05m</span>
          <span><i class="ph ph-gauge" aria-hidden="true"></i>Intermediate</span>
        </div>
        <div class="ns-chero__actions">
          <a class="ns-btn ns-btn--primary" href="#">Start free</a>
          <a class="ns-btn ns-btn--outline" href="#">Syllabus</a>
        </div>
      </div>
    </div>
  </div>
</section>

Console

The brand navy plus the hairline grid — the house style, and the one that needs no assets at all. Composes ns-pattern from the patterns layer rather than inventing a background.

// Free · 4 lessons

Your first org, in an afternoon

Sign up, find your way around, build one object and one automation. Nothing to install.

No setup 48m
markup
<section class="ns-chero ns-chero--console ns-pattern ns-pattern--blueprint">
  <div class="ns-chero__inner">
    <div class="ns-chero__grid">
      <div class="ns-chero__body">
        <span class="ns-chero__kicker">// Free · 4 lessons</span>
        <h1 class="ns-chero__title">Your first org, in an afternoon</h1>
        <p class="ns-chero__lede">Sign up, find your way around, build one object and one automation. Nothing to install.</p>
        <div class="ns-chero__meta">
          <span><i class="ph ph-rocket-launch" aria-hidden="true"></i>No setup</span>
          <span><i class="ph ph-clock" aria-hidden="true"></i>48m</span>
        </div>
        <div class="ns-chero__actions">
          <a class="ns-btn ns-btn--white ns-btn--lg" href="#">Start now — free</a>
        </div>
      </div>
      <div class="ns-chero__media">
        <span class="ns-ph" aria-hidden="true"></span>
      </div>
    </div>
  </div>
</section>

Split

Copy one side, the cover art the other, both on the page surface. The other heroes put the media BEHIND the copy, which is why they all need on-dark ink — this is the one to use when the artwork matters as artwork.

// Developer track

Bulk-safe Apex patterns

Triggers that survive the 200-record data load — the one skill that separates code that works on your desk from code that works in production.

9 lessons2h 10mIntermediate
markup
<header class="ns-chero ns-chero--split" style="inline-size:100%">
  <div class="ns-chero__inner">
    <div class="ns-chero__grid">
      <div class="ns-chero__body">
        <span class="ns-chero__kicker">// Developer track</span>
        <h1 class="ns-chero__title">Bulk-safe Apex patterns</h1>
        <p class="ns-chero__lede">Triggers that survive the 200-record data load — the one skill that separates code that works on your desk from code that works in production.</p>
        <div class="ns-chero__meta"><span>9 lessons</span><span>2h 10m</span><span>Intermediate</span></div>
        <div class="ns-chero__actions">
          <a class="ns-btn ns-btn--primary" href="#0">Start the course</a>
          <a class="ns-btn ns-btn--outline" href="#0">Syllabus</a>
        </div>
      </div>
      <span class="ns-chero__media ns-ph" aria-hidden="true"></span>
    </div>
  </div>
</header>

Certification

For a course whose end state is an exam. The badge sits beside the title at display size rather than being mentioned in the meta row, because for this reader the badge IS the product.

// Certification track

Platform Developer I

Six weeks, five courses, one exam. Every objective on the outline, in the order the exam asks them.

5 courses18h 40mExam-aligned
Certified Platform Developer
markup
<header class="ns-chero ns-chero--cert" style="inline-size:100%">
  <div class="ns-chero__inner">
    <div class="ns-chero__grid">
      <div class="ns-chero__body">
        <span class="ns-chero__kicker">// Certification track</span>
        <h1 class="ns-chero__title">Platform Developer I</h1>
        <p class="ns-chero__lede">Six weeks, five courses, one exam. Every objective on the outline, in the order the exam asks them.</p>
        <div class="ns-chero__meta"><span>5 courses</span><span>18h 40m</span><span>Exam-aligned</span></div>
        <div class="ns-chero__actions"><a class="ns-btn ns-btn--primary" href="#0">Start the track</a></div>
      </div>
      <span class="ns-certbadge ns-certbadge--specialist">
        <span class="ns-certbadge__plate" aria-hidden="true"></span>
        <span class="ns-certbadge__ribbon" aria-hidden="true"></span>
        <span class="ns-certbadge__inner">
          <i class="ph ph-cloud ns-certbadge__mark" aria-hidden="true"></i>
          <span class="ns-certbadge__rule" aria-hidden="true"></span>
          <span class="ns-certbadge__word">Certified</span>
          <span class="ns-certbadge__name">Platform Developer</span>
        </span>
      </span>
    </div>
  </div>
</header>

Accessibility contract

  • The scrim on --cover / --video is not optional: text over an arbitrary photograph has no contrast guarantee, and a hero whose legibility depends on which image the editor picked is broken by design
  • The background clip is decoration — muted, loop, playsinline, and hidden entirely under prefers-reduced-motion, which leaves exactly the --cover version
  • The play control over the preview is a real button with a name, never a decorative triangle
  • The title is the page's h1; the kicker above it is not a heading