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.
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.
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.
The Salesforce admin trail
Six courses in one order, from your first org to a passing score on the ADM-201.
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.)
Integration patterns, live
Four weeks, four live builds, one recording of each — with the whole cohort in the same room.
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.
SOQL, properly
Selective queries, relationship traversal, and the index behaviour that decides whether your report loads or times out.
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.
Your first org, in an afternoon
Sign up, find your way around, build one object and one automation. Nothing to install.
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.
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.
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.
Platform Developer I
Six weeks, five courses, one exam. Every objective on the outline, in the order the exam asks them.
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