Skip to main content

Kinds of site

Blog or newspaper

A blog or a newspaper, on any CMS: a prompt for an LLM, and recipes for its header, page header, post cards, article header, table of contents and footer.

Paste the prompt into any LLM. It asks about your blog and your CMS in short rounds, shows you the plan and writes nothing until you say "go".

Open the prompt

Or build it yourself from the recipes below. It works with any CMS or static site generator: each recipe is HTML for one of its templates, and the CMS fills in the text. They use the classes of core, the catalog and cms only; Install LUZ lists the files to load.

The skip link, the site header with the name of the blog and its sections, the <main> and the footer. For a newspaper, the masthead does not stick. The search and the language switch are the catalog's elements: leave them out if you do not load it.

At 768 px of window and below, the sections fold into the catalog's navbar menu. The example does not stick: on a page, .o-sticky keeps it at the top.

HTML
<body class="o-page">
  <a class="luz-skip-link" href="#main-content">Skip to content</a>

  <header class="luz-site-header luz-site-header--publication o-sticky">
    <div class="o-container o-container--inline o-row">
      <button class="luz-nav-toggle" type="button" popovertarget="cms-nav" aria-label="Sections">
        <svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false"><g fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 6h16M4 12h16M4 18h16"/></g></svg>
      </button>
      <a class="luz-site-header__brand" href="/">The Vejer Review</a>
      <nav class="luz-navbar" id="cms-nav" aria-label="Sections" popover>
        <ul class="luz-navbar__list">
          <li><a class="luz-navbar__link" href="/news/" aria-current="true">News</a></li>
          <li><a class="luz-navbar__link" href="/culture/">Culture</a></li>
          <li><a class="luz-navbar__link" href="/opinion/">Opinion</a></li>
        </ul>
      </nav>
      <div class="o-row luz-site-header__actions">
        <luz-search>…</luz-search>
        <luz-lang-switch>…</luz-lang-switch>
      </div>
    </div>
  </header>

  <main id="main-content" class="o-container o-stack" tabindex="-1">
    <!-- a page header and a list of posts, or an article -->
  </main>

  <!-- the footer -->
</body>

The title of a page that is not a story: a section, an archive, the About page. The page header holds its <h1> and one sentence.

Coast

The sea, the port and the beaches of Vejer, and the people who work on them.

HTML
<div class="luz-page-header">
  <h1 class="luz-page-header__title">Coast</h1>
  <p class="luz-page-header__lead">The sea, the port and the beaches of Vejer, and the people who work on them.</p>
</div>

Post card

One post in a list: a picture, its section, the title, a line of summary and the date. It is core's card, with no CSS of its own. The link on the title makes the whole card one link, with one tab stop; the section is a tag, not a second link.

A list of posts is the post list, a <ul> that fits columns of 16rem or more; the markup below also works on .o-grid--auto. More cards, the related posts and the author box are in CMS templates.

HTML
<ul class="o-grid o-grid--auto">
  <li class="luz-card">
    <div class="luz-image luz-image--3x2 u-mb-sm">
      <img src="/img/tide-gauge-640.jpg" width="640" height="427" alt="" loading="lazy" decoding="async">
    </div>
    <p class="luz-tag luz-tag--gray u-mb-sm">Coast</p>
    <h2 class="luz-card__title"><a href="/2026/10/tide-records/">What ten years of tide records say about the bay</a></h2>
    <p class="luz-card__body">Volunteers have read the gauge in the port twice a day since 2016.</p>
    <p class="luz-meta"><time datetime="2026-10-12">12 October 2026</time> <span>6 min read</span></p>
  </li>
  <!-- one li for each post -->
</ul>

Article header

The top of a story: its section, the title, a standfirst, the byline with the date and the reading time, and the lead picture. The article header holds the story's <h1>; the date and the reading time are core's meta line.

Coast

What ten years of tide records say about the bay

Volunteers have read the gauge in the port twice a day since 2016. The sea is four centimetres higher.

The tide gauge in the port, at low tide.
HTML
<header class="luz-article-header">
  <p class="luz-article-header__kicker"><a href="/coast/">Coast</a></p>
  <h1 class="luz-article-header__title">What ten years of tide records say about the bay</h1>
  <p class="luz-article-header__standfirst">Volunteers have read the gauge in the port twice a day since 2016. The sea is four centimetres higher.</p>
  <div class="luz-article-header__byline">
    <span class="luz-avatar luz-avatar--lg"><img src="/authors/ana-ruiz-96.jpg" width="48" height="48" alt=""></span>
    <div>
      <p>By <a href="/authors/ana-ruiz/">Ana Ruiz</a></p>
      <p class="luz-meta"><time datetime="2026-10-12">12 October 2026</time> <span>6 min read</span></p>
    </div>
  </div>
  <figure class="luz-article-header__media">
    <div class="luz-image">
      <img src="/img/tide-gauge-1280.jpg" width="1280" height="720" alt="A green gauge post marked in centimetres, in shallow water by a stone quay" fetchpriority="high" decoding="async">
    </div>
    <figcaption>The tide gauge in the port, at low tide. Photo: Ana Ruiz.</figcaption>
  </figure>
</header>

Table of contents

The sections of a long story, beside its text: the table of contents, in an <article> with the text as core's prose. Leave it out of a short post, and the layout is the text alone.

Since March 2016, a group of volunteers has read the tide gauge in the port at six in the morning and six in the evening.

How the readings were taken

Each reading is the height of the water against the gauge, to the nearest centimetre, with the time and the wind.

Four centimetres in ten years

The average height at high tide was 4 cm higher in 2025 than in 2016.

Beside the text when the article is 46rem wide or more, above it below that. With the catalog's script, the section in view is marked as you scroll.

HTML
<article class="luz-article">
  <header class="luz-article-header">…</header>
  <div class="luz-article__layout">
    <nav class="luz-toc" aria-labelledby="toc-title" data-luz-spy>
      <h2 class="luz-toc__title" id="toc-title">Contents</h2>
      <ol class="luz-toc__list">
        <li><a href="#method">How the readings were taken</a></li>
        <li><a href="#level">Four centimetres in ten years</a></li>
      </ol>
    </nav>
    <div class="luz-prose">
      <p>Since March 2016, a group of volunteers has read the tide gauge…</p>
      <h2 id="method">How the readings were taken</h2>
      <p>…</p>
      <h2 id="level">Four centimetres in ten years</h2>
      <p>…</p>
    </div>
  </div>
</article>

Who publishes the blog and the links a reader looks for last, in one row: the site footer.

A <div> here: a page has one footer landmark, and this page has its own.

HTML
<footer class="luz-site-footer">
  <div class="o-container o-container--inline o-row">
    <p>The Vejer Review is published by a cooperative.</p>
    <nav class="o-actions" aria-label="Links">
      <a class="luz-btn luz-btn--ghost luz-btn--sm" href="/corrections/">Corrections</a>
      <a class="luz-btn luz-btn--ghost luz-btn--sm" href="/accessibility/">Accessibility statement</a>
    </nav>
  </div>
</footer>