The Bearded Developer

Design System

Every colour, typeface, component and interaction used across this site, in one place.

This is not a mood board. Each example below is the real component, rendered from the same code that runs the live site, with the classes and behaviour that produce it written alongside. It exists so you can judge the standard of the design and front-end work without picking through a website page by page.

It is built with Next.js and Tailwind CSS v4, and it is the same approach we take to bespoke web application work and to Shopify and BigCommerce storefronts. Hover, focus and scroll the examples — the states and animations are live.

8

Brand colour tokens

2

Typefaces

40+

Documented components

1

Codebase they all come from

Foundations

Colour

Eight brand tokens defined as CSS custom properties in the Tailwind theme layer. The palette is deliberately cool and narrow: a teal family carries almost everything, with a single warm accent held in reserve. Nothing on the site uses a colour outside this list except the semantic callout scale below.

#131515

Brand Black

brand-black

Hero and footer backgrounds, primary body text, headings.

#006D77

Brand Blue

brand-blue

Solid buttons, active pagination, gradient start on CTA panels.

#028090

Brand Teal

brand-teal

The primary accent. Link hovers, eyebrow labels, icon badges, rules.

#83C5BE

Brand Light Blue

brand-light-blue

Gradient end on CTA panels, accent text on dark backgrounds.

#EDF6F9

Brand Platinum

brand-platinum

Hover states in menus, quiet section fills, button hover text.

#E29578

Brand Orange

brand-orange

Reserved warm accent. Used sparingly against the teal family.

#FFDDD2

Brand Light Orange

brand-light-orange

Soft warm fill for tinted panels.

#FFFFFF

Brand White

brand-white

Card surfaces, nav bar, the default page background.

Semantic callout scale

Long-form content uses a fixed seven-colour scale so a reader learns the meaning once and carries it across every article. Colours are never mixed between meanings.

Warning

Problems, failure symptoms, what goes wrong.

bg-red-50 border-l-4 border-red-500

Informational

Diagnostic steps, how-to instructions, neutral guidance.

bg-blue-50

Positive

Quick fixes, delivered outcomes, recommendations.

bg-green-50

Caution

When to call in help, things to keep an eye on.

bg-yellow-50 border-l-4 border-yellow-500

Secondary

Moderate severity, secondary recommendations.

bg-orange-50

Comparison

Contrast panels when weighing one platform against another.

bg-purple-50

Neutral

Background context and supporting detail.

bg-gray-50

Text tone ramp

Rather than a set of grey tokens, secondary text is expressed as opacity against brand-black. This keeps text harmonious on both white and tinted surfaces.

100%The quick brown fox jumps over the lazy dog
80%The quick brown fox jumps over the lazy dog
70%The quick brown fox jumps over the lazy dog
60%The quick brown fox jumps over the lazy dog
50%The quick brown fox jumps over the lazy dog
40%The quick brown fox jumps over the lazy dog

Foundations

Typography

Two typefaces, both variable weight and loaded through next/font with display: swap. Lexend carries every heading, label and button; Montserrat carries running text. The split is strict — a heading never uses Montserrat and a paragraph never uses Lexend.

Headings

Lexend

Aa Bb Cc Dd Ee Ff Gg

0123456789

Variable weight, latin subset. Applied per-element via lexend.className rather than a global rule, so headings opt in explicitly.

Body

Montserrat

Aa Bb Cc Dd Ee Ff Gg

0123456789

Set on the body element in the root layout, so it is the default for everything that does not ask for Lexend.

Type scale

Sizes are responsive pairs rather than a fixed ramp — most headings step up once at the md breakpoint and again at xl for the hero.

Displaytext-4xl md:text-5xl xl:text-6xl font-bold leading-[1.06] tracking-tight

Build better

Homepage hero headline only. One per page.

Page titletext-5xl md:text-6xl font-bold

Design System

The h1 on every top-level page and the h2 on homepage sections.

Article titletext-4xl md:text-5xl font-bold

Celigo error troubleshooting

Article body h2, one step down from a page title.

Section headingtext-2xl font-semibold

How the sync actually works

Article h3 and card titles. Always paired with mt-8.

Lead paragraphtext-lg md:text-xl font-semibold

So, what can we do for you?

Sits directly under a page title. Montserrat, not Lexend.

Bodytext-base leading-relaxed

Helping UK businesses build better e-commerce stores.

Default running text. Montserrat.

Smalltext-sm text-brand-black/60

Practical insights, no noise and no fluff.

Supporting copy, card body text, sidebar content.

Eyebrow label

A single recurring device: small, uppercase, wide-tracked Lexend in teal. It sits above headings, labels footer columns, marks partner panels and titles form fields. Tracking varies between 0.12em and 0.18em depending on how much room it has.

What we do

Shopify & Celigo Certified

Free consultation

Classes

text-xs font-semibold uppercase tracking-[0.15em] text-brand-teal ${lexend.className}

Foundations

Layout & spacing

Every page is built from the same two primitives. Container fixes the measure, Section provides vertical rhythm, and an inner md:p-10 gives content room to breathe on desktop while staying edge-to-edge on mobile.

Container and Section

Container caps content at max-w-6xl (1152px) and applies a uniform 20px gutter. Section is a positioned wrapper that establishes stacking context for decorative blobs and waves.

Container — max-w-6xl mx-auto p-5

Section — relative my-5

Content — md:p-10

Page content sits here.

Classes

// Container max-w-6xl mx-auto p-5 // Section relative my-5 // Inner content block md:p-10 relative z-20

Vertical rhythm

Spacing is deliberately coarse. Major page sections are separated by my-20, headings are followed by mt-5 on mobile and mt-10 from md up, and paragraphs within a block use mt-4 or mt-6.

my-2080pxBetween major page sections
mt-1040pxTitle to lead paragraph (desktop)
mt-832pxBefore an article section heading
mt-624pxBetween article paragraphs
mt-416pxWithin a callout or card
gap-4 / gap-1016 / 40pxTight grids / content grids

Breakpoints

Standard Tailwind breakpoints plus a custom 3xl at 120rem. The navigation is the one component that switches at lg rather than md, to make room for the extra top-level item.

sm

640px

md

768px

lg

1024px

xl

1280px

2xl

1536px

3xl

1920px

Foundations

Shape & elevation

Corner radius signals scale: the larger the surface, the softer the corner. Buttons and tags are always fully rounded. Elevation is used sparingly — most surfaces are separated by a hairline border rather than a shadow.

Radius

rounded-md

Pagination cells

rounded-lg

Callouts, inputs, panels

rounded-xl

Tiles, menus, fact panels

rounded-2xl

Cards, mega menu, CTA blocks

rounded-full

Every button and tag

Elevation

shadow-sm

Resting cards and tiles

shadow-md

Nav on scroll, card hover

shadow-lg

Service cards

shadow-xl

CTA panels, dropdowns

shadow-2xl

Services mega menu

Borders

A hairline border does most of the work of separating surfaces. Three weights are in use across the whole site.

border-gray-100

Dividers inside menus and cards.

border-gray-200

The default card and tile outline.

border-brand-teal/40

Hover and active state on interactive tiles.

Foundations

Motion

Animation is used for one job: bringing content in as you reach it. Entrance animations are defined as paused CSS animations and only start once an ancestor picks up the in-view class from an intersection observer, so nothing animates off-screen and nothing runs twice at once.

Entrance animations

Scroll this panel out of view and back to replay them. Each class sets animation-play-state: paused; a single rule — .in-view .in-up — releases them. Stagger is applied per element with an inline animationDelay rather than nth-child rules.

.in-up

from translateY(50px)

The default. Headings, paragraphs, cards, grid items.

.in-right

from translateX(-50px)

Content that reads in from the left edge.

.in-up-right

from translate(-50px, 50px)

Diagonal entrance for section headings and achievement blocks.

Classes

.in-up { animation: animation-in-up 1s both paused; animation-timing-function: cubic-bezier(0.455, 0.03, 0.515, 0.955); } .in-view .in-up { animation-play-state: running; }

Stagger

Grids cascade by deriving the delay from the item index. Testimonials use index / 3 + 2, technology tiles use index / 9 + 1 — the divisor sets how tightly the cascade bunches up.

0
1
2
3
4
5
6
7
8
9
10
11

Classes

style={{ animationDelay: `${index / 9 + 1}s` }}

Decorative blocks

A background flourish for dark panels. Six columns of bars drop in from above with a slight overshoot on the way down, staggered across roughly four seconds and held at 10% opacity so they never compete with the content in front of them.

Classes

@keyframes animation-block { 0% { opacity: 0; transform: translateY(-150px); } 25% { opacity: 1; } 50% { transform: translateY(5px); } 100% { opacity: 1; transform: translateY(0px); } }

Duration scale

Durations map to how far the element has to travel and how much the user is waiting on it. Anything under a pointer resolves in 300ms or less.

150msMenu items and tag hovers — near-instant feedback
200msNav links, input focus, icon wells
300msCards, tiles and accordion expansion
500msButtons and the nav bar hiding on scroll
1000msEntrance animations
4000msThe hero button pulse, looping

Easing

Two custom curves are registered in the theme layer alongside the entrance curve baked into the keyframe classes.

ease-fluid

cubic-bezier(0.3, 0, 0, 1)

ease-snappy

cubic-bezier(0.2, 0, 0, 1)

entrance

cubic-bezier(0.455, 0.03, 0.515, 0.955)

Classes

--ease-fluid: cubic-bezier(0.3, 0, 0, 1); --ease-snappy: cubic-bezier(0.2, 0, 0, 1); // entrance cubic-bezier(0.455, 0.03, 0.515, 0.955);

Components

Buttons & actions

Every action on the site is a pill. There are two families: the animated SCSS button used for the primary 'Let's talk' call to action, and a set of Tailwind-only pills that invert their fill and text colour on hover over 500ms. Hover the examples below to see the transitions.

Primary — hero call to action

The main conversion button. A continuous 4-second pulse draws a soft teal glow around it, and hovering fills the button from a 3px inset ring out to solid. Reserved for the single most important action on a page, normally on a dark background.

Classes

animated-button animated-button-fill min-w-48 hover:text-brand-black uppercase font-semibold transition-all duration-500 transform lg:scale-110
Source
src/app/buttonAnimations.scss
Animation
pulseAnimation, 4s ease-in-out, infinite
Hover
inset ring expands to solid fill, 0.5s
Height
60px (icon-size token)

Primary — compact

The same animated button with the glow and pulse removed and the height reduced to 40px. Used in the navigation bar, inside expanded service rows, and anywhere the full-size version would dominate.

Classes

animated-button animated-button-fill animated-button-small min-w-36 text-brand-black hover:text-brand-platinum font-semibold transition-all duration-500 flex items-center
Size
60 × 40px, widened by min-w-36
Resting
Solid #7de2d1 fill, no shadow
Hover
Fill darkens to brand-black

Solid pill

The workhorse secondary action — 'Read', 'Explore Articles', 'View Code'. Inverts completely on hover: the brand-blue fill becomes white and the outline picks up the blue.

Default / disabled at 50% opacity

Classes

outline outline-2 outline-white hover:outline-brand-blue bg-brand-blue text-white hover:bg-white hover:text-brand-blue px-6 py-2 rounded-full transition-colors duration-500 uppercase font-semibold

Ghost on gradient

Used on the teal gradient CTA panels where a solid button would compete with the background. A white 2px outline over a transparent fill, inverting to a solid white pill on hover.

Classes

w-48 outline outline-2 outline-white bg-transparent text-white hover:bg-white hover:text-brand-blue px-6 py-2 rounded-full transition-colors duration-500 uppercase font-semibold

Article call to action pair

Every long-form article closes with a gradient panel carrying two actions: a filled white primary pointing at the relevant service page, and an outlined blue secondary pointing at contact.

Classes

// Primary bg-white text-blue-600 px-6 py-3 rounded-full font-semibold hover:bg-gray-100 // Secondary bg-blue-600 text-white px-6 py-3 rounded-full font-semibold hover:bg-blue-700 border-2 border-white

Text links

Inline actions that sit in body copy or at the foot of a panel. All use teal as the resting colour and shift to brand-blue on hover, with an arrow to signal direction of travel.

Visit RC Boat EnginesFree consultation - let's discuss your projectAn inline link inside article copy

Classes

inline-flex items-center gap-2 text-sm font-semibold text-brand-teal hover:text-brand-blue transition-colors

Pagination

Fixed 32px square cells with a 6px radius — the only place on the site where a control is not a pill. The current page is filled; the rest invert to brand-blue on hover. The list is clamped to two pages either side of the current one.

123

Classes

w-8 h-8 flex items-center justify-center border rounded-md bg-white text-brand-black hover:bg-brand-blue hover:text-white hover:outline hover:outline-brand-blue transition-colors duration-500

Tags

Three tag treatments, all fully rounded and uppercase-free. Article tags are the heaviest, technology tags sit one step lighter, and related-service tags are interactive — they fill with teal on hover.

CeligoNetSuiteIntegrationsArticle tags
Next.jsTailwind CSSNetSuiteTechnology tags
Related servicesShopifyIntegrations

Classes

// Article bg-gray-200 text-gray-800 rounded-full px-2 py-1 text-xs font-semibold // Technology bg-gray-100 text-gray-700 rounded-full px-3 py-1 text-xs font-semibold // Service link + hover:bg-brand-teal hover:text-white transition-colors

Components

Cards & surfaces

Card surfaces share one recipe: white fill, a gray-200 hairline, a 16px radius and a shadow only where the card needs to lift off the page. Interactive cards signal it by warming their border to teal on hover rather than by moving.

Review card

A flex column so the author block always pins to the bottom regardless of quote length. Opens with an oversized serif quotation mark at 25% teal — decorative and hidden from screen readers.

One word - AMAZING! I had several problems with my website and James sorted them out for me in the space of 2 days, highly recommend.

Jackie T

Cotton and Twigg

Classes

flex flex-col bg-white border border-gray-200 rounded-2xl p-6 shadow-sm hover:shadow-md hover:border-brand-teal/30 transition-all duration-300

Testimonial figure

The longer-form counterpart to a review card, used for LinkedIn recommendations pulled from the CMS. Semantic figure and blockquote elements, with the quote glyph as inline SVG.

James was very attentive to my project needs and asked the right questions. We are absolutely thrilled at what he has built for us.

Jake E

Director - RC Boat Engines Ltd.

Classes

bg-brand-platinum/5 rounded-lg p-5 h-full flex flex-col in-up

Service accordion row

The homepage services list. Rows are stacked inside one rounded container with dividers between them; hovering or focusing a row expands it. The open row takes a soft tinted fill, a 4px teal left border and rotates its arrow 90 degrees. The expand animation uses a grid-rows 0fr to 1fr transition, so it works without measuring content height.

Celigo Integration Services

Integration DesignManaged SupportError Monitoring

We deliver Celigo integration services from architecture through ongoing managed support.

Bespoke Solutions

DiscoveryCustom Web Apps

Classes

// open {bgColor} border-l-4 border-l-brand-teal // closed bg-white hover:bg-brand-platinum border-l-4 border-l-transparent // expansion grid transition-all duration-300 grid-rows-[0fr] → grid-rows-[1fr]

Technology tile

Logos rest in greyscale at 50% opacity and come to full colour on hover, so the grid reads as texture until a visitor looks for something specific. The label shifts to teal at the same time.

Next.jsNext.js
ReactReact
Tailwind CSSTailwind CSS
NetSuiteNetSuite

Classes

bg-white border border-gray-200 rounded-xl p-4 flex flex-col items-center gap-3 hover:border-brand-teal/40 hover:shadow-sm transition-all duration-300 // logo: filter grayscale opacity-50 group-hover:grayscale-0 group-hover:opacity-100

Project facts panel

Used where a project has no screenshots. A divide-y list turns key figures into a scannable column, with the label in wide-tracked uppercase and the value in semibold Lexend.

Platform

BigCommerce

Integration

NetSuite via Celigo

Engagement

Ongoing retainer

Classes

bg-gray-50 rounded-xl p-6 divide-y divide-gray-200

Client logo tile

Client marks sit at 60% opacity until hovered, which keeps a grid of mismatched logos looking even. Each tile takes an optional background colour, so a logo drawn for a dark background still reads properly in a grid of white tiles.

Shopify
Celigo
NetSuite
Go

Classes

h-full rounded-xl border border-gray-200 p-8 flex justify-center items-center opacity-60 hover:opacity-100 transition-all duration-300 // background comes from the client record, defaulting to #ffffff

Partner badge panel

A bordered white panel that groups credentials under teal eyebrow headings, split by a hairline. Each logo sits on its own light grey plinth so partner marks of different shapes still align.

Certified Partners

Platforms We Specialise In

Thumbnail

Article and project images crop to a fixed 256px height inside a rounded mask, so a mixed set of source images still produces an even grid. The image scales to 105% on hover while the mask holds its shape.

Example article thumbnail

Classes

// wrapper mt-4 overflow-hidden rounded-xl // image object-cover w-full h-64 shadow-xs hover:scale-105 hover:shadow-xl transition-all duration-200

Components

Forms & inputs

There is one form pattern on the site and it lives on a teal gradient card. Fields are translucent white over that gradient rather than solid boxes, which keeps the card reading as a single object. The whole form swaps for a confirmation panel on submit rather than showing an inline message.

Contact form

Labels are the teal eyebrow treatment inverted to white. Inputs use a 20% white fill with a 30% border, brightening to a solid white border and a soft ring on focus. The textarea is fixed at min-h-36 with resize disabled so the card cannot be pulled out of shape.

Classes

// input w-full rounded-lg bg-white/20 border border-white/30 text-white placeholder-white/50 px-4 py-3 text-sm focus:outline-none focus:border-white focus:ring-1 focus:ring-white/50 // label block text-xs font-semibold uppercase tracking-[0.14em] text-white/80 mb-1.5
Card
bg-gradient-to-br from-brand-blue to-brand-light-blue
Radius
rounded-2xl, p-8, shadow-xl
States
idle → pending → success | error

Pending state

Success state

Message sent

We'll get back to you as soon as possible.

Error state

Something went wrong

Please try again or contact us directly.

Toggle switch

Built on Headless UI's Switch, so keyboard and screen reader behaviour comes from the library rather than being hand-rolled. Off is gray-200, on is brand-blue, and a locked-on switch drops to 50% opacity. Try them.

Strictly necessary

Always on and cannot be turned off.

Analytics

Helps us understand how the site is used.

Marketing

Used to measure campaign performance.

Classes

h-6 w-11 rounded-full bg-gray-200 data-[checked]:bg-brand-blue transition-colors duration-200 // knob: size-5 rounded-full bg-white group-data-[checked]:translate-x-5

Contact method pills

Not a form control, but the fallback beside every form. A circular teal-tinted icon well inverts to solid teal on hover while the label underlines — the whole row is one target.

info@thebeardeddeveloper.co.uk+44 (0) 330 043 5977

Classes

// icon well w-8 h-8 rounded-full bg-brand-teal/10 text-brand-teal group-hover:bg-brand-teal group-hover:text-white transition-all duration-200

Components

Content blocks

Long-form articles are built from a small kit of repeating blocks. The colour of a block carries meaning, so a reader who has read one article already knows what a yellow panel is about to tell them before they read a word of it.

Callout boxes

A tinted fill, an optional 4px left border for the two tones that need urgency, a Lexend heading in the 900 shade and a bulleted list in the 800 shade at text-sm. Nothing else varies between them.

Warning

Signs your integration is failing

  • Orders appearing in your ERP hours after they were placed
  • Stock levels that disagree between systems

Informational

How to check it yourself

  • Open the flow dashboard and filter to the last 24 hours
  • Compare the record count against your order report

Positive

The quick fix

  • Re-run the failed batch from the error console
  • Set an alert so the next failure reaches you first

Caution

When to call someone in

  • The same error returns after every re-run
  • You are editing a flow you did not build

Classes

bg-[tone]-50 p-6 rounded-lg border-l-4 border-[tone]-500 // heading: font-semibold text-[tone]-900 // list: list-disc list-inside space-y-2 text-[tone]-800 text-sm

Outcome callout

A compact variant used on project entries. The heading is set in small uppercase rather than sentence case, which stops it competing with the project title above it.

What we delivered

A rebuilt order sync that cut manual re-keying to zero and gave the operations team a single place to see failures.

Classes

bg-green-50 p-5 rounded-lg border-l-4 border-green-500 // heading: font-semibold text-green-900 text-sm uppercase tracking-wide

Pull quote

A 4px teal left border with generous left padding and an oversized serif quotation mark at 25% opacity above the text. Used for the founder introduction and anywhere a first-person voice needs setting apart.

I've been building websites and solving tech problems for over 20 years from my base here in Braintree, Essex.

Classes

border-l-4 border-brand-teal pl-6 md:pl-8 // glyph: text-5xl text-brand-teal/25 font-serif select-none

Secondary call to action

The panel that closes almost every page. A blue-to-light-blue gradient carrying an oversized heading, one supporting line capped at max-w-xl, and a ghost button. Title, description, label and destination are all overridable, so the same component adapts per page.

Need Something Custom?

Let's work together to create a custom solution that meets your needs. Contact us today.

Classes

bg-gradient-to-br from-brand-blue to-brand-light-blue rounded-xl shadow-xl p-10 text-white

Message banner

A shorter, denser CTA for mid-page. Three layers build the surface: a three-stop gradient, a white dot-grid at 10% opacity, and a soft bloom in the top-right corner. Content sits above them on z-10.

Free consultation

Ready to move your project forward?

Don't wait - message us today.

Classes

// layer 1 bg-gradient-to-br from-brand-blue via-brand-teal to-brand-light-blue // layer 2 radial-gradient(circle, rgba(255,255,255,0.8) 1px, transparent 1px) / 22px 22px @ opacity-10 // layer 3 radial bloom, -top-20 -right-20, w-64 h-64, opacity-20

Article call to action

The in-article variant, on a blue-to-purple gradient that deliberately sits outside the brand palette so it reads as an interruption rather than part of the article.

Struggling with a Celigo integration?

We offer managed support retainers that keep your flows running and your team out of the error console.

Achievement heading

A heading with a gradient underline that hugs the text rather than spanning the column, because the h4 is set inline-block.

Multi-warehouse stock sync

Classes

// h4 is inline-block; the rule is a block span inside it bg-gradient-to-br from-teal-200 to-brand-teal h-1 rounded-full block

Patterns

Page layouts

Three templates cover the whole site: a dark hero for the homepage, a two-column article layout with a sticky sidebar, and a plain single-column page for services and resources. Everything else is a variation on one of them.

Dark hero

The homepage opening. Four layers stack up on brand-black: a teal dot grid, a radial vignette that fades the grid at the edges, a soft teal bloom in the top-left, then the content. Trust signals sit between the headline and the body copy, separated by 4px teal dots.

BigCommerce, Shopify & Bespoke Software Developer Essex & UK

20+ years experienceUK-basedFree consultation

Helping UK businesses build better e-commerce stores, automate their operations, and grow.

Classes

// dot grid radial-gradient(circle, rgba(2, 128, 144, 0.18) 1px, transparent 1px) / 28px 28px // vignette radial-gradient(ellipse 80% 80% at 50% 50%, transparent 20%, #131515 75%) // bloom radial-gradient(circle, rgba(2, 128, 144, 0.12) 0%, transparent 70%)

Wave transitions

Two SVG waves handle every transition between a dark band and the white page. wave2 closes the hero and is pulled up by -mt-5 to hide the seam; wave1 opens the footer, with the footer content pulled up over it at lg and above.

wave2 — dark to light · wave1 — light to dark

Article template

A three-column grid where the body takes two and the sidebar takes one. The sidebar is sticky from md up with a 40px offset, so the quick reference and service links stay in view for the length of a long read. On mobile the sidebar drops below the article.

Article title over its header image

The meta description doubles as the standfirst, so it is written once and works in both places.

A section heading

Body copy runs at the full width of the two-column span. Every article links to at least one service page and two or three related articles.

A callout sits inline with the copy

Classes

// grid section: md:p-12 relative grid md:grid-cols-3 gap-8 body: md:col-span-2 sidebar: md:col-span-1 bg-gray-100 p-6 rounded-lg mt-10 md:mt-0 md:sticky top-10

Article list item

A five-column grid giving three columns to the text and two to the thumbnail. Below md the thumbnail moves inline under the description rather than being dropped, so mobile readers still get the image.

Celigo error troubleshooting guide

What the common failures actually mean

CeligoNetSuiteIntegrations

A plain-English walkthrough of the errors that show up most often in Celigo, and what to do about each one.

Classes

grid md:grid-cols-5 gap-10 content-stretch justify-between py-16 text: md:col-span-3 · image: md:col-span-2 hidden md:block

Patterns

Principles & conventions

The rules that keep the system consistent as it grows. Most of them exist because breaking them caused a problem once.

Accessibility

Icon-only controls carry a hidden label

The hamburger, the quotation glyphs and the decorative blobs are all handled explicitly — either an sr-only span naming the control, or aria-hidden and an empty alt where the element is purely decorative.

Repeated links are disambiguated

Seven cards saying 'Learn More' is a screen reader problem. Each one carries an aria-label naming its destination, plus an sr-only continuation inside the link text.

State is announced, not just drawn

The services accordion sets aria-expanded, pagination sets aria-current on the active page, and the toggle switch is built on Headless UI so its role and state come from the library.

Keyboard paths match pointer paths

The services list responds to focus as well as hover, and handles Enter and Space, so a keyboard user reaches the same expanded content a mouse user does.

Focus is visible where it matters

Interactive rows use focus-visible:ring-2 focus-visible:ring-brand-teal/70 rather than removing the outline outright.

Code conventions

Tokens live in CSS, not in a config file

Tailwind v4 means the brand palette, the custom 3xl breakpoint and the easing curves are declared in an @theme block in globals.scss. That file is the single source of truth for the design tokens.

Fonts are opted into, never inherited

Montserrat is set once on the body. Lexend is applied per element with lexend.className, so a heading using the display face is always explicit in the markup.

Class names are always complete strings

Variants are selected by picking a whole class string from a lookup, never by building one from fragments — Tailwind only ships classes it can see in full at build time.

Client components are the exception

Almost everything renders on the server. The 'use client' directive appears only where there is genuine interactivity: the navigation, the services accordion, the contact form, the intersection observer and the cookie controls.

Content data sits above the component

Service lists, technology logos, client marks and footer links are declared as arrays at the top of their file and mapped over. Adding an item is a data edit, not a markup edit.

Writing style

Copy is part of the design system. The rules below apply to every heading, label and paragraph on the site.

UK English

Colour, organisation, licence, recognise, catalogue.

Plain language

Written for an operations manager, not a developer. Technical terms are explained the moment they appear.

No padding

If it fits in one sentence, it gets one sentence. Nothing is inflated to sound more impressive.

Concrete over abstract

Real scenarios and real numbers rather than general claims about efficiency.

Where this work applies

A design system is only worth building if it makes the real work faster and more consistent. These are the services it feeds into, and some further reading if you want to see how we think.

Services

  • Bespoke Software custom web applications built on this foundation
  • Shopify theme development and custom storefronts
  • BigCommerce API-first builds and platform migrations
  • AI practical tooling with an interface people will actually use

Like What You See?

If this is the standard you want for your own site or product, let's talk about what you're building.

Let's talk

Stay in the loop

Practical insights on integrations, e-commerce platforms, and bespoke development - no noise, no fluff.

© 2026 The Bearded Developer Ltd.
Company No. 15975190  ·  Braintree, Essex