Airbnb iOS Design System Best Practices
Opinionated, strict design system engineering for SwiftUI iOS 26 / Swift 6.2 apps. Contains 50 rules across 8 categories, prioritized by impact. Derived from Airbnb's Design Language System (DLS), Airbnb Swift Style Guide, Apple Human Interface Guidelines, and WWDC sessions. Mandates @Equatable on every view, @Observable for state, and style protocols as the primary component API.
Mandated Architecture Alignment
This skill is designed to work alongside swift-ui-architect . All code examples follow the same non-negotiable constraints:
- Feature modules depend on Domain
- DesignSystem ; no direct Data dependency
-
@Observable for mutable UI state, ObservableObject / @Published never
-
@Equatable macro on every view
-
Style protocols as the primary component styling API (Airbnb DLS pattern)
-
Asset catalog as the source of truth for color values
-
Local SPM package for design system module boundary
Scope & Relationship to Sibling Skills
This skill is the infrastructure layer — it teaches how to BUILD the design system itself. When loaded alongside sibling skills:
Sibling Skill Its Focus This Skill's Focus
swift-ui-architect
Architecture (modular MVVM-C, route shells, protocol boundaries) Design system infrastructure (tokens, styles, governance)
ios-design
Using design primitives (semantic colors, typography) Engineering the token system that provides those primitives
ios-ui-refactor
Auditing/fixing visual quality issues Preventing those issues via governance and automation
ios-hig
HIG compliance patterns Asset and component infrastructure that makes compliance easy
Clinic Architecture Contract (iOS 26 / Swift 6.2)
All guidance in this skill assumes the clinic modular MVVM-C architecture:
- Feature modules import Domain
- DesignSystem only (never Data , never sibling features)
-
App target is the convergence point and owns DependencyContainer , concrete coordinators, and Route Shell wiring
-
Domain stays pure Swift and defines models plus repository, *Coordinating , ErrorRouting , and AppError contracts
-
Data owns SwiftData/network/sync/retry/background I/O and implements Domain protocols
-
Read/write flow defaults to stale-while-revalidate reads and optimistic queued writes
-
ViewModels call repository protocols directly (no default use-case/interactor layer)
When to Apply
Reference these guidelines when:
-
Setting up a design system for a new iOS app
-
Building token architecture (colors, typography, spacing, sizing)
-
Creating reusable component styles (ButtonStyle, LabelStyle, custom DLS protocols)
-
Organizing asset catalogs (colors, images, icons)
-
Migrating from ad-hoc styles to a governed token system
-
Preventing style drift and enforcing consistency via automation
-
Building theming infrastructure for whitelabel or multi-brand apps
-
Reviewing PRs for ungoverned colors, hardcoded values, or shadow tokens
Rule Categories by Priority
Priority Category Impact Prefix Rules
1 Token Architecture CRITICAL token-
6
2 Color System Engineering CRITICAL color-
7
3 Component Style Library CRITICAL style-
10
4 Typography Scale HIGH type-
5
5 Spacing & Sizing System HIGH space-
5
6 Consistency & Governance HIGH govern-
7
7 Asset Management MEDIUM-HIGH asset-
5
8 Theme & Brand Infrastructure MEDIUM theme-
5
Quick Reference
- Token Architecture (CRITICAL)
-
token-three-layer-hierarchy
-
Use Raw → Semantic → Component token layers
-
token-enum-over-struct
-
Use caseless enums for token namespaces
-
token-single-file-per-domain
-
One token file per design domain
-
token-shapestyle-extensions
-
Extend ShapeStyle for dot-syntax colors
-
token-asset-catalog-source
-
Source color tokens from asset catalog
-
token-avoid-over-abstraction
-
Avoid over-abstracting beyond three layers
- Color System Engineering (CRITICAL)
-
color-organized-xcassets
-
Organize color assets with folder groups by role
-
color-complete-pairs
-
Define both appearances for every custom color
-
color-limit-palette
-
Limit custom colors to under 20 semantic tokens
-
color-no-hex-in-views
-
Never use Color literals or hex in view code
-
color-system-first
-
Prefer system colors before custom tokens
-
color-tint-not-brand-everywhere
-
Set brand color as app tint, don't scatter it
-
color-audit-script
-
Audit for ungoverned colors with a build script
- Component Style Library (CRITICAL)
-
style-dls-protocol-pattern
-
Define custom style protocols for complex DLS components
-
style-equatable-views
-
Apply @Equatable to every design system view
-
style-accessibility-first
-
Build accessibility into style protocols, not individual views
-
style-protocol-over-wrapper
-
Use Style protocols instead of wrapper views
-
style-static-member-syntax
-
Provide static member syntax for custom styles
-
style-environment-awareness
-
Make styles responsive to environment values
-
style-view-for-containers-modifier-for-styling
-
Views for containers, modifiers for styling
-
style-catalog-file
-
One style catalog file per component type
-
style-configuration-over-parameters
-
Prefer configuration structs over many parameters
-
style-preview-catalog
-
Create a preview catalog for all styles
- Typography Scale (HIGH)
-
type-scale-enum
-
Define a type scale enum wrapping system styles
-
type-system-styles-first
-
Use system text styles before custom ones
-
type-custom-font-registration
-
Register custom fonts with a centralized extension
-
type-max-styles-per-screen
-
Limit typography variations to 3-4 per screen
-
type-avoid-font-design-mixing
-
Use one font design per app
- Spacing & Sizing System (HIGH)
-
space-token-enum
-
Define spacing tokens as a caseless enum
-
space-radius-tokens
-
Define corner radius tokens by component type
-
space-no-magic-numbers
-
Zero hardcoded numbers in view layout code
-
space-insets-pattern
-
Use EdgeInsets constants for composite padding
-
space-size-tokens
-
Define size tokens for common dimensions
- Consistency & Governance (HIGH)
-
govern-naming-conventions
-
Enforce consistent naming conventions across all tokens
-
govern-spm-package-boundary
-
Isolate the design system as a local SPM package
-
govern-single-source-of-truth
-
Every visual value has one definition point
-
govern-lint-for-tokens
-
Use SwiftLint rules to enforce token usage
-
govern-design-system-directory
-
Isolate tokens in a dedicated directory
-
govern-migration-incremental
-
Migrate to tokens incrementally
-
govern-prevent-local-tokens
-
Prevent feature modules from defining local tokens
- Asset Management (MEDIUM-HIGH)
-
asset-separate-catalogs
-
Separate asset catalogs for colors, images, icons
-
asset-sf-symbols-first
-
Use SF Symbols before custom icons
-
asset-icon-export-format
-
Use PDF/SVG vectors, never multiple PNGs
-
asset-image-optimization
-
Use compression and on-demand resources
-
asset-naming-convention
-
Consistent naming convention for all assets
- Theme & Brand Infrastructure (MEDIUM)
-
theme-environment-key
-
Use EnvironmentKey for theme propagation
-
theme-dont-over-theme
-
Avoid building a theme system unless needed
-
theme-tint-for-brand
-
Use .tint() as primary brand expression
-
theme-light-dark-only
-
Use ColorScheme for light/dark, not custom theming
-
theme-brand-layer-separation
-
Separate brand identity from system mechanics
How to Use
Read individual reference files for detailed explanations and code examples:
-
Section definitions - Category structure and impact levels
-
Rule template - Template for adding new rules
Reference Files
File Description
references/_sections.md Category definitions and ordering
assets/templates/_template.md Template for new rules
metadata.json Version and reference information