A tray of three shared component cards with copies drifting out along dotted gold paths, the furthest copy dashed to show drift.

Shared components for Drupal multisite: fighting drift

Why multisite drift needs a smaller, shared component library instead of tighter governance, and what has to be true for one to survive real variation.

The pattern

A multisite platform launches with a shared theme and a handful of sites. Two years in, every site has drifted. A department wanted a slightly different card layout, another needed a hero variant nobody else uses, a third has a one-off region that exists because a deadline mattered more than architecture that week. None of these decisions was wrong on its own. The sum of them is a platform where changing anything shared means auditing every site to see who forked the thing you’re about to touch.

The usual response is governance: a design system document, a review process, a rule that new patterns need sign-off. My argument is that governance slows the drift without stopping it. The incentive that produced the drift in the first place never goes away. A real site has a real deadline and a real reason its case is the exception. A document nobody consults under deadline pressure is a compliance cost, paid by whoever remembers to read it.

Shrink what each site owns

The alternative is shrinking what’s unique per site down to configuration, so there’s less surface for drift in the first place. A site that can only choose from a defined set of card layouts, hero variants and colour tokens can still look different from its neighbours. It can’t fork the underlying markup to get there, because the markup belongs to the component. The site picks a configuration of it.

That only works if the shared library is built for variation. A component with one hardcoded appearance and no sanctioned way to adjust it reproduces the original problem one level up. The first team that needs something the library doesn’t offer will fork it the way they forked the theme, because forking was always the fastest path and a rigid library changes nothing about that.

Where the objection holds

Institutions differ. A medical school and a business school have different audiences, different content and different visual expectations from their own leadership. A shared component library will eventually meet a requirement it wasn’t built for. Then one of two things happens. The library bends until every prop is optional and every behaviour overridable, and the design system it was meant to enforce stops existing. Or the site forks anyway, and you’re back where you started.

That failure mode is real. The defence I’d propose is naming, up front, which axes of variation are sanctioned (colour, spacing, a defined set of layout variants). Anything outside them becomes a request for a new variant, reviewed and added once, instead of a private escape hatch reached for under deadline pressure. The difference lies in who decides what’s allowed to vary, and where that decision is recorded.

What that looks like in a module

bootstrap_components (Bootstrap 5 Components) is my attempt at that shape. The current release, 1.0.1, ships 21 Single Directory Components for Drupal 10 and 11. The development version trims that to 18, and the card shows where it is heading: title, subtitle, text, links and image are simple props so a card can be filled in one step, and variation is declared as options. The card has default, horizontal and overlay layouts under core’s variants: key, and header, content and footer slots for anything nested inside it:

components/card/card.component.yml (development version, excerpt)
name: Card
variants:
default:
title: Default
horizontal:
title: Horizontal
overlay:
title: "Image overlay"
slots:
header:
title: Header
content:
title: Content
footer:
title: Footer

A site picks from those options and never owns a copy of the card’s Twig. The claim the module makes is a small one: adding a new variant to a shared library, reviewed once, costs less over a platform’s lifetime than every site solving the same problem its own way.

What isn’t settled

The variant set didn’t come from studying multisite platforms. The README credits most of the component structure to ui_suite_bootstrap, trimmed to a smaller subset that is easier to audit, so the options it ships are Bootstrap’s own. About a dozen sites report using it on drupal.org, which is nowhere near enough to say whether those options hold up across a large multisite platform.

If you’ve run a multisite platform where the shared-component approach broke down for a reason beyond a skipped review, I’d like to know what it was. That is the failure I haven’t seen yet, and the one that would move the line I’ve drawn between sanctioned variation and a real gap in the library.

What this came from