Categories
Code & Development UX Audit UX Design UX Musings

A Developer’s Guide to Pragmatic Design Systems

Building a full-scale enterprise design system for a small project is overkill. You can build one that’s pragmatic, however.

The Core Premise: Don’t Overdo it

You don’t have to build a full-scale enterprise design system for a small project. Overly complex, ad-hoc styles, can lead to maintenance nightmares in the future. A pragmatic design system isn’t about massive documentation, it’s about locking in a handful of foundational rules upfront so your UI naturally looks cohesive without constant tweaking and overriding.

We want pragmatic, not trendy

This is for developers who don’t have an in-house designer and anyone building an app that wants it to look more cohesive, quickly. I’m avoiding the term “modern” because what does that even mean? Usually it means “trendy” which is not what we want. We want a solid design that users will see and immediately trust.

Spend a little time at the beginning of a project with the following steps, and you’ll be well placed to create a solidly designed website or application.

Section Breakdown

The following are some fundamental steps you can follow to get your project looking good without too much fuss.

1. The Developer’s Dilemma: Handling Cognitive Load & Micro-Decisions

  • The Problem: Constant micro-decisions (“Should this button be 12px or 16px padding?”, “What hex code was the alert yellow again?”) slow down development and cause UI decay.
  • The Fix: Shift from choosing values during feature development to consuming predefined constraints. Good constraints means good design.
  • The Goal: Set your visual rules once, make them predictable, and then forget about them.

2. Foundational Architecture: The Core Design Tokens

  • What Are Tokens at a Small Scale? The absolute minimum set of primitive values needed to power an interface.
  • Color System Architecture:
    • Core Brand/Primary: 1 primary color for key actions.
    • Surfaces & Text: High-contrast baseline (background, card surface, primary body text, secondary text).
    • Status Signals: Standardized functional colors (success, alert, error).
    • Follow the 60/30/10 color rule: The primary colour should be 10% of the colour used on a page. 60% is text colour and the other 30% is a secondary support colour to primary. Too much primary colour means it loses impact.
    • Small Colour system: I like to use the Tailwind Colour Generator to create colour wheels from 50-950. Then if you want to make it really flexible you run oklch with an @supports fallback, check out the codepen for this here using SCSS.
    • Rule: Never use arbitrary raw hex values directly in component styles. Use custom properties (CSS variables). That way you can make changes to the variables and everything related to that variable follows suit.
  • Typography Hierarchy:
    • Define a strict, mathematical scale (e.g., Minor Thirds) for headings (H1–H6), body, and small text.
    • Establish fixed vertical rhythm rules (line-heights and baseline spacing) founded on the base font size (14px or 16px).
  • Spatial System (The 4px / 8px Grid):
    • Limiting layout choices to a simple numeric scale (xs: 4px, sm: 8px, md: 16px, lg: 24px, xl: 32px) for padding, margins, and gaps.

3. Setting “Set-and-Forget” Defaults

  • Global Reset & Base Rules:
    • Establishing default font sizes, line heights, and body background colors at :root sets a dependable baseline that you can then safely override.
    • Defaulting form fields, buttons, and containers to standard padding and focus states further supports consistency.
  • Designing for Automatic Hierarchy:
    • Structure visual weight so that high-priority elements demand attention naturally (e.g., primary buttons pop, secondary buttons recede) without needing inline override styles.

4. Creating Reusable Component Patterns

  • The Base Component Rule:
    • Separate base container styles from variation skins.
    • Keeping base components minimal: Containers, Typography/Labels, Buttons, Data Cards, and Input Controls.
  • Enforcing Consistency:
    • How to construct layout wrappers (flex/grid containers) with fixed gap values to ensure white space is consistent across every view.

5. Practical Execution & Workflow Integration

  • Managing Tokens in Code:
    • Storing tokens as CSS custom properties (variables), JSON config objects, or central theme objects depending on your stack.
  • The “Tweak Last” Discipline:
    • Resist the urge to add custom inline overrides when building a screen.
    • If a layout looks off, fix the token or container spacing default rather than applying a local hotfix.

Everything needs to work together for a design to look solid

This is the goal!

By Nathaniel Flick

Hi I'm Nathaniel, a Senior Product Designer & UX Engineer focused on user-centred innovation for growing companies. I'm a designer who codes. I create innovative, user-focused digital experiences, blending Design Thinking with a deep understanding of web development principles.

Leave a Reply

Your email address will not be published. Required fields are marked *