The first part of the book does two jobs. It argues that the frontend deserves an architect in the same way a backend does, and it lays down the first of four pillars: the code itself. Godbolt spends little time on syntax. What he cares about is the relationship between HTML and CSS, because that relationship decides whether a component can be moved, reused, tested and deleted without side effects.

For me this is the most durable part of the book. The arguments about specificity, location-dependent styles and who owns a variation are the ones I still have in React code reviews. The tools changed; the failure modes did not.

Chapters 1 to 7 in the book.

Key ideas

The architect's users are other developers

The book defines frontend architecture as a set of tools and processes whose goal is better frontend code and a smoother, more sustainable workflow. The architect designs the system everyone codes within, plans the path from a line of code to production, and keeps adjusting that path as the project changes. Godbolt is explicit that this does not mean writing less code. It means the audience of your code changes: you write linters, build scripts, templates and rules for the developers around you instead of only features for end users.

Two consequences follow. The architect needs to be on the project early, because some decisions (markup ownership, CSS conventions, how templates are shared with the CMS) are expensive to reverse. And the four pillars are a checklist of conversations, not a curriculum: chapter 3 accepts that a small project may do very little in some pillars.

Pillar The question it forces
Code What do our HTML, CSS and JS look like, and how do we know?
Process How does an idea become deployed code, and what is automated?
Testing How do we know today's change did not break yesterday's work?
Documentation Where does knowledge live, and who is it written for?

Chapter 2, "Alpha Project", sets up the case study: Red Hat wanted to share its website bands across other company sites, and the team's wish list (modular content, comprehensive testing, streamlined processes, exhaustive documentation) became the four pillars. The first months were slower than usual, but each later request needed less and less new work.

There is no page, only a system

Chapter 4 walks through three ways markup gets produced. In the CMS-driven world, the backend generates deeply nested wrappers and the frontend can only style what it is given. In the hand-written world, the frontend controls everything but has to update every page by hand, which pushes people towards long descendant selectors. The goal is the third option: markup generated by templates that the frontend team owns, so every instance of a navigation or card uses the same structure and the same classes.

That leads to the book's central reframing. A URL no longer maps to a fixed page, because content varies by user, time and device. What you actually build is a design system: the code version of the visual language that designers created, broken into small parts with rules for recombining them. Once you see it that way, a ticket that says "update the About page" stops making sense, and the unit of work becomes a component or a variation.

Choosing a CSS methodology for its reasons

The book compares OOCSS, SMACSS and BEM on the same toggle widget, then refuses to pick a winner. What matters is understanding which problem each one attacks:

Methodology Main idea worth keeping
OOCSS Separate structure from skin, and stop using location as a style qualifier
SMACSS Sort styles into base, layout, module, state and theme, with layouts and modules in separate places
BEM Every class names its block, element and modifier, so it means the same thing everywhere

Chapter 5 shows why this matters with a sidebar heading. Styling #sidebar h2 creates five problems at once: a specificity contest, colours you must reset, a component that changes when moved, one element inheriting from several sources, and ever deeper selectors for anything nested. Flat, single-class selectors fix all five. Red Hat mixed SMACSS and BEM, and Godbolt is fine with combining ideas as long as the team commits to one written approach.

A single selector for everything

Chapter 5 introduces the principles and chapter 7 shows Red Hat applying them under the heading "a single selector for everything". Godbolt had spent years writing generic classes that could go on any element, and found that nobody dared change them, so people kept adding new ones. The fix was the opposite: every element gets one flat, unique class that belongs to its component.

Single responsibility here means a class is made for one purpose in one place, not for one group of properties. If the blog title and the calendar title share .primary-header, a change to one silently changes the other, and deleting a component risks breaking whatever borrowed its styles. Single source of truth goes further: every rule that can affect an element, including how it looks inside another context, lives in that component's file.

Variations follow the same logic. Red Hat put modifiers and contexts in data attributes instead of extra classes, so the class names what the thing is and the attribute names how it varies. A class is only on or off; an attribute carries a name and a value, which gives it a built-in namespace. And every modifier is opt-in: a component reacts to data-align only if its own file defines what that means. Here is the idea in my own words and a different domain:

@layer components {
  .price-tag {
    display: grid;
    gap: var(--space-1);
  }

  .price-tag__amount {
    font-size: var(--font-size-lg);
    color: var(--color-text);
  }

  .price-tag[data-tone="sale"] .price-tag__amount {
    color: var(--color-danger);
  }

  [data-theme="dark"] .price-tag__label {
    color: var(--color-text-inverse);
  }
}

The dark-theme rule is a context, but it sits in the price tag's file, so anyone reading this file sees every visual state the component can be in. That is what makes visual regression coverage tractable later: the list of variations is finite and written down.

type PriceTagProps = {
  label: string;
  amount: string;
  tone?: "default" | "sale";
};

export function PriceTag({ label, amount, tone = "default" }: PriceTagProps) {
  return (
    <div className="price-tag" data-tone={tone}>
      <span className="price-tag__label">{label}</span>
      <strong className="price-tag__amount">{amount}</strong>
    </div>
  );
}

The cost is some repetition when several components support the same modifier. Godbolt accepts it, and so do I: shared mixins or tokens remove most of it without reintroducing cascade surprises.

The Road Runner Rules and semantic grids

Chapter 7 opens with the launched Red Hat site and why it could not be shared: dependency bloat (every band silently assumed Bootstrap and a huge core stylesheet) and location-dependent selectors scoped to page and band classes. The rebuild broke the designs into a handful of layouts and a small set of dumb components. To keep merge requests true to that split, the team wrote the Road Runner Rules, named after a list of rules said to have been given to the writers of the Road Runner cartoons to keep that universe consistent. They even wrote rules for the rules: only immutable rules, not instructions; each boiled down to its shortest form; state the rule, then what to do instead; and every rule uses a word like always, never, only, every, do or don't. Here are the rules as I understand them:

Rule, in my words Why it matters
A layout only handles alignment and spacing of its children, never their padding or inner styles Layouts and components stay swappable
Themes and data attributes are contexts that things opt into, never forced changes A theme cannot restyle a component that did not ask for it
A component fills its container on all four sides: no top or left margins inside, trailing margins cleared Any components dropped side by side line up
The component root has no background, width, float, padding or margin; styles target only its inner elements The surrounding layout decides those
Every element has one unique, component-scoped class, changed only by contexts and themes You can change or delete a component without side effects
Elements never use top margins; the first one sits flush with the top Rows of components align without fixes
JavaScript never binds to a class; behaviour opts in through a data attribute Renaming or restyling cannot break behaviour

Semantic grids are how layouts were applied. Instead of a dedicated band per layout, or Bootstrap-style row and column wrappers around every child, the parent region gets one data attribute naming a grid pattern (galleries of four or five, splits of a 12-column grid). The children carry no grid classes and no wrappers, so the markup stays about content, and switching a logo wall from five to four columns is one attribute change. A needed layout outside the inventory gets built, documented and added to it. With CSS grid that inventory is short:

@layer layouts {
  [data-layout] {
    display: grid;
    gap: var(--space-4);
  }

  [data-layout="gallery-4"] {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  [data-layout="gallery-5"] {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }

  [data-layout="split-3-9"] {
    grid-template-columns: 1fr 3fr;
  }
}

JavaScript: start with less

Chapter 6 is short. Its advice is to assume you need no framework, CMS or CSS library until a requirement proves otherwise, to lint everything in the build, and to write small named functions instead of long selector-plus-callback chains. The jQuery examples have aged badly, but the principle that the architect sets a written baseline so code review is fair has not.

Reading it in 2026

The problems in these chapters are real; the toolbox for solving them is much better now.

  • Cascade layers. @layer lets you declare the order of reset, tokens, layouts and components explicitly, so a component rule wins because of its layer, not because of a longer selector. Cascade layers have been Baseline Widely available since September 2024.
  • Scoping. CSS Modules, framework-scoped styles and now @scope give you component boundaries without naming conventions doing all the work. @scope became Baseline Newly available in December 2025 with Firefox 146, so check your browser targets before relying on it.
  • Container queries. The rule that components are context-free gets easier when a component can respond to its own container width instead of the viewport. Container size queries are Baseline Widely available as of 2025.
  • Design tokens. The colours, spacing and type scales Godbolt calls the visual language now usually live as tokens. The Design Tokens Community Group published its first stable format, version 2025.10, in October 2025, with Style Dictionary, Tokens Studio and Terrazzo among the reference implementations.
  • Data attributes for state are now mainstream in component libraries. Headless libraries such as Radix expose states like data-state="open" for styling, which is very close to the opt-in modifier idea.
  • Sass. If you still use Sass, @import is deprecated in Dart Sass in favour of @use and @forward, and is slated for removal in Dart Sass 3.0. JSHint has largely given way to ESLint and TypeScript's own checks.
  • Layouts. CSS grid makes semantic grids nearly free: a named grid-template-columns per data attribute value, as in the example above.

What I would not carry forward is the heavy reliance on BEM naming in a React codebase that already has scoping. The underlying rules (flat selectors, one owner per style, explicit variations) still apply; the naming scheme is optional once the tooling enforces boundaries.

Putting it to work

  1. Write your own Road Runner Rules in the always/never/only style and keep the list under ten items. Put it in the repo, not a wiki.
  2. Declare a layer order once (for example reset, tokens, layouts, components, utilities) and stop fixing conflicts with !important or longer selectors.
  3. Audit components for outer margins and fixed widths. Move spacing to layout primitives such as a stack or grid component.
  4. Express variants as typed props that render a data attribute, and keep every variant and context rule in the component's own stylesheet.
  5. When a ticket says "change this page", rewrite it as "add this variation to this component" before anyone starts coding.
  6. Before adding a framework or UI kit, list the requirements it solves that you cannot cover with the platform and a few utilities.

Check yourself

  1. Why does Godbolt say the architect's audience is developers? Because the architect's main output is the system others work within: conventions, templates, build and test tooling. Feature code for end users is only part of the job.

  2. What are the five problems with styling #sidebar h2? Specificity battles, having to reset inherited colours, location dependence, multiple inheritance from several selectors, and ever deeper selectors for nested content.

  3. How does single source of truth differ from single responsibility? Single responsibility says a class serves one element in one component. Single source of truth says every rule that can change that element, including contextual ones, lives in that component's file.

  4. Why must components avoid outer margins and backgrounds? So any component can drop into any layout slot and line up with its neighbours; spacing and surfaces are the layout's job.

  5. What makes a grid "semantic" in Red Hat's sense? The layout is a named value in one data attribute on the parent, so children need no grid classes or row and column wrappers.

  6. Which 2026 CSS feature most directly replaces selector length as a tie-breaker? Cascade layers, which make precedence a matter of declared layer order rather than specificity.

Further reading