Airbnb's DLS: the system that refused atomic design

Airbnb's DLS gets quoted for its polish. The interesting part is a structural decision made early and stated plainly: components are organisms with a contract, not assemblies of shared atoms. That choice is why the system survived four platforms, and it is the same choice that decides whether your system survives being read by a coding agent.

Updated July 27, 2026

Independent analysis based on publicly published accounts by Airbnb's design team, written for people building their own systems. Identity Forge is not affiliated with or endorsed by Airbnb. Airbnb and its logo are trademarks of their owner.

The decision everyone skips

In the design team's own published account of the DLS, the founding structural choice is stated directly: instead of relying on individual atoms, they considered components as elements of a living organism — each with a function and a personality, defined by a set of properties, able to coexist with others and to evolve or die independently. The stated benefit is the absence of a complicated network of interconnected parts.

That is a rejection of atomic design, made by a team that had the resources to implement atomic design properly and chose not to. It is worth taking seriously rather than treating as a stylistic preference, because the reasoning generalises.

Atomic compositionSelf-contained organism
A component isAn assembly of shared smaller componentsA unit with declared required and optional elements
Changing a shared buttonPropagates everywhere, including places nobody checkedChanges the button. Each component owns its own presentation
ReuseMaximal — that is the pointDeliberate, at the component level
DuplicationMinimalSome, accepted as the price of independence
Cross-platformHard. The atom tree has to exist identically on every platformEasier. Only the contract has to match
Failure modeOne change breaks four surfaces silentlyTwo components drift apart because nobody noticed
Two ways to define a component, and what each one costs when you change something.

Neither column is correct in general. The right answer depends on which failure mode you can afford. A single-platform web product with a small team can absorb the propagation risk and gets real value from the reuse. A system spanning iOS, Android, tablet and web cannot, because the atom tree has to be reproduced identically in Swift, Kotlin, and whatever the web stack is that year — and it will not be.

The divider rule

One detail from the DLS account explains the whole philosophy better than the philosophy does. Rather than having divider lines exist as their own elements between components, each component is required to contain its own divider, shown or hidden by view logic.

Consider what the alternative costs. If dividers live between components, then whether a divider appears is a property of the list, not the row — so the list has to know it is the last row, on four platforms, in four codebases, including in the case where a row is conditionally hidden. Every list implementation reimplements that logic and one of them gets it wrong. Move the divider inside the row and the rule becomes local: a row knows whether it draws its own bottom edge, and nothing above it has to reason about position.

The generalisable rule: when a visual property depends on context, push it into the component and give the component a way to be told about its context. Do not make every container reimplement the same conditional. This is one of the few design-system decisions that is almost always right.

The same document notes that the elements defining each component were declared in both the Sketch file and the code. That is the other half of the contract: a component is not defined by its rendering on any one platform, but by the list of things it must contain. Sketch and Swift are two implementations of the same declaration.

Platform-agnostic, with named exceptions

The DLS is described as mostly platform-agnostic — most components look and work the same on iOS and Android — while deliberately following native conventions on a short list of things: navigation, system iconography, contextual actions, and interactions. The Android navigation bar differs from the iOS one and uses a different icon, by design.

The short list is the interesting part. A system that tries for total parity produces an app that feels foreign on both platforms; a system that defers to platform convention everywhere produces two products that share a logo. The DLS draws the line at the elements users have learned from the operating system rather than from your product. Back navigation is an OS convention. A pricing row is not.

Belongs to the platformBelongs to your system
ExamplesBack/up navigation, share affordance, system icons, scroll physics, contextual menus, keyboard behaviourColour roles, type scale, spacing, component composition, content structure, motion personality
WhyUsers learned it from the OS, not from you. Overriding it costs themUsers learn it from you. Diverging costs you
If you get it wrongThe app feels subtly hostile and nobody can say whyThe app feels like two different companies
Where a cross-platform system should and should not diverge.

The same document notes the system was built so identical code, components and designs work across device sizes, with a small set of layout rules handling the tablet transformation. That is the same principle applied to a different axis: keep one definition, add rules for the axis that genuinely varies.

Why a contract survives translation

The thread running through all of this is that the DLS's unit of truth is a declaration, not an implementation. A component is a name plus a list of required elements, optional elements, and behavioural properties. Swift, Kotlin, the web build and the Sketch library are four renderings of that declaration.

This is why the approach scaled across platforms while an atom-tree approach would not have. A contract can be satisfied by any implementation. A composition tree can only be satisfied by reproducing the tree, and the moment one platform's framework makes that awkward, someone works around it and the systems fork.

A contract can be satisfied by any implementation. A composition tree can only be satisfied by reproducing the tree.

It is also why the model applies to a platform nobody was thinking about in 2015.

The agent is another platform

When a coding agent writes your interface, it is doing exactly what the iOS team did: rendering your system in an environment with its own idioms and constraints, from whatever definition you handed it. Every question the DLS had to answer comes back unchanged.

Cross-platform DLSAgent-facing system
What is unified?Component contract, tokens, structureColour roles, type scale, spacing, prohibitions, motifs
What is platform-specific?Navigation, system icons, contextual actionsFramework, component library, file layout, class syntax
Where the definition livesSketch library plus code, kept in sync by a teamA file in the repository the agent reads
How divergence shows upTwo apps that feel like different companiesTwo screens in the same app that feel like different companies
The same question, asked about a native platform and about an agent.

The last row is the practical difference, and it is the reason this matters more now than it did then. A cross-platform drift takes a release cycle to appear and a designer notices. Agent drift appears within one session, between two files, and nobody notices until the third screen.

We sampled 299 DESIGN.md files published for AI agents to read, to see how much of a contract they actually contain. 86% specified colours as raw hex values with no role attached — a value list, not a contract. 76% contained no prohibitions of any kind. 44% contained no concrete size value anywhere, and 54% leaned on at least one vague adjective, most often "clean" (39%) or "modern" (36%).

A file like that is the atomic-design failure in prose form. It hands over parts with no statement of what they are for, and every screen the agent writes reassembles them differently. What the DLS would have written instead is a declaration: this component requires these elements, this colour has this role, this is not allowed.

## Card

Required: title, supporting text
Optional: image, badge, footer action
Contains its own bottom divider; hidden when last in a list.

Padding: 16px. Radius: 12px. Border: 1px --border-subtle.
Never uses a drop shadow — elevation is a surface step.
Never uses the accent colour for its border or background.

That is thirty seconds of writing, and it is the difference between an agent that produces the same card on screen fourteen and one that invents a new one.

Identity Forge design kits are built as this kind of contract — semantic colour roles, an explicit do's and don'ts list, motifs and layout rules — and serialise to a DESIGN.md any coding agent can read. Browse the kits or start with what a DESIGN.md file is.

What is worth copying, and what is not

The DLS is not available to install, and chasing its visual output would be the wrong exercise anyway — it was designed for a travel marketplace with photography as the primary content, which is a specific problem most products do not have.

What transfers is three decisions, all of which cost nothing to adopt:

  1. Define components by contract, not composition. Write down required elements, optional elements and properties. Let the implementation be whatever each target needs.
  2. Push context-dependent visuals into the component. The divider rule, generalised. If a container has to know something about its children to render them correctly, you have put the logic in the wrong place.
  3. Name the short list of things that are allowed to diverge. Everything else is unified by default. A system without that list either forces false parity or drifts everywhere.

None of those require a design systems team, a Sketch library, or four platforms. They require deciding what your components are, which is the work most systems skip on the way to picking colours.

Can I download or install the Airbnb design system?

No. The DLS is not published as an installable package or a public documentation site. What is available is the design team's written accounts of how it was built, plus third-party Figma reconstructions that are one person's interpretation rather than a spec.

Why did Airbnb reject atomic design?

Their published reasoning was that treating components as assemblies of shared atoms creates a complicated network of interconnected parts. Treating each component as a self-contained unit with defined required and optional elements lets components evolve or be retired independently — which matters far more when the same system has to exist in Swift, Kotlin and web code.

Is atomic design wrong, then?

No, it is a different trade-off. Atomic composition minimises duplication and is a good fit for a single-platform product with one codebase. It costs you propagation risk and cross-platform fidelity. Airbnb had four platforms and chose the other side. Pick based on which failure you can absorb.

What should stay the same across platforms and what should differ?

Keep your colour roles, type scale, spacing, component contracts and content structure identical everywhere. Defer to the platform on things users learned from the operating system rather than from you: back navigation, system iconography, share affordances, contextual menus, scroll and keyboard behaviour.

How does this apply to AI coding agents?

An agent is another platform rendering your system in an unfamiliar idiom. It needs the same thing a native team needed — a contract stating what each component requires, what each colour is for, and what is forbidden. Most design guidance written for agents is a value list instead, which is why output drifts between screens.