Most people building a small WordPress site reach for a page builder right away. That skips something. A page builder hands you layout controls, sure—but it doesn’t hand you a design system. Without one, you get visual drift, spacing that makes no sense, and a maintenance headache that grows with every new landing page.
I picture a workshop. A page builder is the tool belt. A design system is the rulebook that says where the benches sit, how high the outlets go, and which fasteners you grab for which materials. You can build without that rulebook. You’ll just end up redoing the work later.
This article walks through what a small-site design system actually needs before you ever open a page builder. We’ll hit the core primitives, the WordPress-specific mechanics, and the kind of documentation that keeps the whole thing from falling apart over time.

The Primitive Layer: Tokens, Not Components
When someone says “design system,” a lot of people picture a component library: buttons, cards, hero sections. That’s the surface. Underneath sits the primitive layer—the stuff that governs what a builder actually spits out.
Primitives are the smallest, non-negotiable values. Colors, type scales, spacing steps, border radii, shadow presets. In WordPress these map straight to CSS custom properties and theme.json settings. Nail those first, and every block and every builder module pulls from the same set of constraints.
Color Tokens That Survive Context
A single hex value isn’t a token. A token is a named role: --color-surface, --color-text-primary, --color-border. You need a palette that holds up in light and dark contexts, with enough contrast to pass accessibility checks. WordPress block themes declare these in theme.json. When a page builder draws from theme.json, your colors stay locked in.
What I build first: a set of 8–12 functional color tokens. No more. Every new color I add later has to justify itself against an existing token. I run into too many small sites with 47 color variables, half of them collecting dust. That’s not a system; it’s a landfill.
Type Scales That Respect the Grid
Typography in a page builder goes sideways when people mix heading levels with random font sizes. A design system pins a type scale to the base spacing unit. If your base spacing is 8px, your line heights and margins should snap to multiples of 8. That keeps vertical rhythm intact when a builder drags a heading next to a paragraph.
I define my type scale in theme.json under settings.typography.fontSizes. Each size gets a slug, a value in rem, and a line-height multiplier. Then I map those slugs to heading levels and block presets. A builder module that respects theme.json will offer exactly those sizes and nothing else.
Spacing That Won’t Drift
Page builders love handing you sliders for padding and margin. Without a spacing scale, you wind up with 13px tops and 27px bottoms on the same card. Define a spacing scale—I lean on a 4px base step with stops at 4, 8, 12, 16, 24, 32, 48, 64, 96px—and enforce it through CSS custom properties or theme.json settings.spacing.spacingScale.
Once that scale is in place, a builder’s spacing controls turn into preset dropdowns instead of freeform inputs. That constraint is the whole point. It speeds up decisions and stops the slow creep of one-off values.

Layout Primitives: Before the Builder’s Canvas
A page builder gives you a blank canvas. That’s the weakness. A design system gives you a constrained canvas with pre-defined zones. Before you crack open a builder, settle on the layout patterns that repeat across the site.
The Content Width and Its Gutters
Every small site needs one content width, one wide width, and gutter values that stay consistent from header to footer. In WordPress, these are theme-side settings: settings.layout.contentSize and wideSize. When a builder respects theme.json, its container blocks snap to these widths automatically.
I set the content width to something readable—often 680px for a text-heavy site, 800px for a portfolio. The wide width lands at 1200px or 1280px. Gutters run 24px on mobile and scale to 32px on desktop. Those numbers aren’t pulled from thin air; they come straight from the spacing scale.
Section Templates as Repeatable Zones
A small site might have 5–7 distinct section types: a hero, a feature grid, a testimonial row, a call-to-action, a footer. Each section type needs a name, a defined inner layout, and spacing rules for what sits above and below it. These aren’t builder templates yet—they’re paper sketches or block patterns with locked spacing.
I write these as block patterns in PHP or as synced patterns in the block editor. They rely on core blocks and theme-defined styles. Later, when I open a page builder, I can reproduce the same zones faster because the rules are already set.
WordPress Mechanics That Hold the System Together
A design system lives in files, not in a builder’s interface. For a WordPress site, the system has to hook into the platform’s architecture. Here are the mechanics I reach for.
theme.json as the Single Source of Truth
Since WordPress 5.8, theme.json has become the configuration backbone. It declares color palettes, typography, spacing, layout, and block defaults. A builder that reads theme.json inherits those settings. A builder that ignores it will fight you every step of the way.
I configure theme.json before installing a builder. I turn on appearanceTools: true to expose border, shadow, and spacing controls. I disable custom font sizes and custom colors at the block level to shut down drift before it starts. These settings become the guardrails the builder has to work inside.

CSS Custom Properties as the Runtime Layer
Tokens defined in theme.json turn into CSS custom properties on the front end. I lean on these hard. Every block style I write references var(--wp--preset--color--primary) instead of a hardcoded hex. If I change the token, every instance updates.
For a builder-created page, this means I can style builder modules by targeting the custom properties they output. Most builders let you slap a CSS class on a module. I write a small stylesheet that maps builder-specific classes to the theme’s custom properties. The builder becomes a layout tool, not a style tool.
Block Patterns as the Bridge
Block patterns are the native WordPress way to bundle a section template. Before I touch a page builder, I build the 5–7 core section patterns using core blocks. This pushes me to solve layout constraints with tools every builder can import or reproduce.
Patterns also pull double duty as documentation. When a client asks why a testimonial section has 48px of bottom padding, the pattern file shows the rule. If you hit structural snags early on—like a “Nothing Found” error on new pages—I covered that in What to Fix First When a New WordPress Site Says Nothing Found.
Documentation That Actually Works
A design system without documentation is a conversation you keep having. For a small site, I don’t write a 40-page spec. I write a single markdown file or a private Notion page with three sections.
The Token Reference
List every color token, its hex value, and its usage rule. List the type scale slugs. List the spacing stops. This section is pure reference—zero prose. When I build a new page, I keep this open in a side tab.
The Section Catalog
Each section type gets a screenshot, its pattern name, and its spacing rules. For example: “Hero section: full-width background, content width container inside, 96px padding top and bottom on desktop, 64px on mobile. Always followed by the first section with 0px top margin.”
The Decision Log
This is the most underrated piece. Every time I make a design decision that strays from the original rules, I log it. “Added a 12px border radius token because cards needed a softer variant for the testimonial section.” Six months later, I can see why a value exists and whether it still belongs.
When You Actually Open the Page Builder
Now the design system has primitives, layout zones, platform hooks, and documentation. The page builder becomes a tool for assembly, not discovery. You’re not picking colors in the builder; you’re picking from a preset. You’re not dragging spacing sliders; you’re choosing from the scale.
This shifts the builder’s role from a design sandbox to a layout accelerator. Sections snap together because the spacing rules are baked in. Typography stays consistent because the builder pulls from the theme’s type scale. The client can add a new page without mangling the visual language—constraints live at the system level, not the page level.
Which Builder Fits This Approach
Not all builders treat theme.json with respect. I look for builders that read global styles and expose them as presets, not as overrides. Builders that let me disable custom colors and font sizes per module jump to the front of the line. If a builder ignores my spacing scale and dangles a freeform slider, I pass.
The block editor itself, when configured with theme.json and custom block patterns, often replaces a third-party builder for small sites. It’s native, so there’s zero extra abstraction between the design system and the rendered page.
Common Pushback and Why I Ignore It
People tell me this is too much process for a five-page brochure site. I don’t buy it. The process I described takes a focused afternoon. The alternative—fixing inconsistent spacing, mismatched colors, and busted layouts across five pages—takes weeks spread over months. The upfront cost is low; the deferred cost stings.
Others say a page builder handles all of this. A builder handles layout; it doesn’t handle design governance. Governance is the system. Without it, the builder turns into a machine for creating variations, and variations are the enemy of a coherent site.
FAQ
Do I need a full design system for a one-page site?
You need the primitives. Even a single page has colors, type, and spacing. Defining those as tokens in theme.json takes minutes and stops the page from turning into a pile of one-off values that look different on every screen.
Can I build a design system with a page builder already installed?
Yes, but you’ll be retrofitting. Start by auditing the existing pages for color, type, and spacing values. Consolidate them into tokens, then apply those tokens to the builder’s global settings. Retrofitting is heavier than building the system first, but it pays off.
What if my page builder does not read theme.json?
You can still enforce the system through CSS custom properties and a shared stylesheet. Map the builder’s class names to your custom properties. It’s manual but effective. If the builder actively fights you—spewing inline styles that override your properties—consider a different builder.
How do I keep the system up to date over time?
Use the decision log. Every change to a token or a pattern gets a dated entry. Review the log quarterly. If a token hasn’t been used in six months, deprecate it. Small sites hoard dead tokens fast; pruning keeps the system lean.





