Design System Enforcement
SGD enforces your organisation's design system at the PR level. When a developer (or AI agent) opens a pull request that modifies .tsx or .jsx files, the platform scans the changed code against your defined rules and reports violations as inline annotations on the diff.
This is not a linter — it is a governance layer that understands your component library, design tokens, and architectural patterns.
Rule types
Your organisation defines design system rules in the SGD dashboard. Each rule falls into one of three types:
| Rule type | What it checks | Example rule | Example violation |
|---|---|---|---|
| Canonical Component | A specific component must come from a specific package | Button must be imported from @acme/ui | import { Button } from './components/Button' |
| Banned Pattern | A code pattern must not appear in component files | No inline styles in .tsx files | Inline style props with raw values |
| Required Token | Specific values must use design tokens instead of literals | Colours must use CSS custom properties | color: #2563eb instead of color: var(--color-primary) |
Canonical Component rules
These are the most impactful rules. They ensure that common UI elements — buttons, modals, tables, form inputs — come from your shared component library rather than being re-implemented per team.
# Example: canonical component rule
- name: canonical-button
type: canonical_component
component: Button
package: "@acme/ui"
severity: warning
message: "Use the shared Button component from @acme/ui"
docs: "https://design.acme.com/components/button"When a PR introduces a custom <Button> component or imports Button from a different package, the check annotates the relevant line with the rule name, message, and a link to the canonical component documentation.
Banned Pattern rules
These rules catch patterns your team has explicitly decided to avoid. Common examples:
# Example: banned pattern rules
- name: no-inline-styles
type: banned_pattern
pattern: "style=\\{\\{"
file_glob: "*.tsx"
severity: error
message: "Inline styles are banned — use CSS modules or design tokens"
- name: no-direct-dom
type: banned_pattern
pattern: "document\\.getElementById"
file_glob: "*.tsx"
severity: warning
message: "Avoid direct DOM manipulation in React components — use refs"
- name: no-any-cast
type: banned_pattern
pattern: "as any"
file_glob: "*.tsx"
severity: warning
message: "Avoid 'as any' casts — use proper type narrowing"Banned patterns with error severity block the merge. Patterns with warning severity annotate but do not block.
Required Token rules
These rules ensure visual consistency by requiring design tokens instead of hardcoded values:
# Example: required token rules
- name: colour-tokens
type: required_token
pattern: "#[0-9a-fA-F]{3,8}"
file_glob: "*.tsx"
severity: warning
message: "Use a design token (e.g., var(--color-primary)) instead of a hex colour"
exceptions:
- "*.test.tsx"
- "*.stories.tsx"
- name: spacing-tokens
type: required_token
pattern: "margin:\\s*\\d+px|padding:\\s*\\d+px"
file_glob: "*.module.css"
severity: info
message: "Consider using spacing tokens (e.g., var(--space-4)) for consistent spacing"Exceptions are important
Notice the exceptions field above. Test files, Storybook stories, and documentation examples should not trigger design system violations. Configure exceptions per rule to avoid false positives.
How it works
Step by step:
Organisation defines rules — In the SGD dashboard, an architect or tech lead creates design system rules using the YAML format above. Rules are scoped to the whole organisation, a specific capability, or individual repositories.
PR opens with component changes — When a PR is opened (or updated) that includes changes to
.tsxor.jsxfiles, the SGD GitHub App receives the webhook event.SGD scans changed files — The platform fetches the changed files via the GitHub API and evaluates them against applicable rules. Only changed lines are checked — existing code is not retroactively flagged.
Violations appear on the PR — Any violations are posted as inline annotations on the PR diff, using GitHub's Check Run annotation API. Each annotation includes the rule name, a human-readable message, and a link to documentation or the canonical alternative.
Results feed into coherence scoring — The design system compliance results are one of the 12 dimensions in the coherence score. Repositories with fewer violations score higher on this dimension.
Only changed lines
SGD only evaluates lines that were added or modified in the PR. It does not flag pre-existing violations in unchanged code. This prevents a wall of noise on the first PR after rules are introduced. Existing violations are tracked separately via the coherence score.
Configuring rules
Scope
Rules can be applied at three levels:
| Scope | Applies to | Use case |
|---|---|---|
| Organisation | All repos in the org | Foundational rules (no inline styles, use design tokens) |
| Capability | All repos in a capability | Capability-specific component library rules |
| Repository | A single repo | Repo-specific exceptions or stricter rules |
When rules conflict, the most specific scope wins. A repository-level rule overrides a capability-level rule, which overrides an organisation-level rule.
Severity
Each rule has a severity that determines its behaviour:
| Severity | PR behaviour | Dashboard behaviour |
|---|---|---|
| error | Blocks merge (check fails) | Counts as a violation |
| warning | Annotates diff (check warns) | Counts as a warning |
| info | Annotates diff (check passes) | Informational only |
What this enables
Design system enforcement is not just about catching mistakes. Over time, it creates:
- Measurable UI consistency — The design system dimension in the coherence score tracks compliance across every repository and capability
- Onboarding acceleration — New developers (and AI agents) get immediate feedback about which components to use, with links to documentation
- Library adoption tracking — You can see exactly which teams are using the canonical component library and where adoption is lagging
- Deprecation management — When you deprecate a component, add a banned pattern rule. Every PR touching the old component gets a migration nudge
The goal is not to punish deviations. It is to make the right path the easy path.