Your Design System Is a Contract: Enforce It with Konsist and Android Lint
Without automated enforcement, design system violations accumulate silently across feature teams, forcing reviewers to repeat feedback and inflating UI maintenance costs. This layered approach converts written guidelines into CI-blocking rules, shifting the burden from human memory to the repository itself.
Design system drift happens because code review is not a reliable enforcement mechanism. The solution is to treat the design system as an engineering contract and automate its checks. For Jetpack Compose, that means layering three tools: Konsist for package and architecture boundaries, custom Android Lint detectors for forbidden source patterns, and Compose UI tests for runtime behavior.
The article walks through defining tokens for spacing, typography, colors, and shapes, then shows how Konsist tests can assert that feature packages never depend on design system internals. It then implements a concrete Lint detector that flags numeric literals in `Color()` constructors outside an approved allowlist, including issue registration, service loader setup, and unit tests that check both violations and legal exceptions.
The final part covers rollout strategy: start with a non-blocking audit, fix high-value violations, then make rules blocking in CI. The argument is that executable rules move design decisions into the repo itself, reducing the cost of maintaining hundreds of slightly different UI implementations.
Code review is not a reliable enforcement mechanism: reviewers are time-constrained and the same feedback recurs across pull requests, so automation shifts responsibility from human judgment to the repository.
No single tool can enforce every design rule; methods must be matched to the kind of constraint, whether structural (Konsist), expression-level (Lint), or runtime (Compose UI tests).
The detector example shows that broad bans on dimension literals would mis-flag legitimate non-spacing uses, so rules need clearly scoped APIs and explicit contracts.
The emphasis on testing both violations and legal exceptions underscores that a detector without tests is just code that can silently fail to enforce anything.
The rollout approach of starting with an audit and then making rules blocking is a pragmatic way to avoid flooding CI with pre-existing violations.