Your repo gives the agent a clear answer for every check in this scan.
Fixes you can make right now to increase the health score
Two of these three fixes could raise the design system health score from 55 to 72. One more pays once it is done in full.
01
Unwind the 26 !important declarations
+11
Each one is a selector losing an argument with another selector; data-grid.css alone carries 8. Fix the specificity at the source and they stop being necessary.
paste it into your agent ·
You are fixing one design-system finding in the telekom-scale repository, measured by roast-my-design-system.
The finding: Unwind the 26 !important declarations
The detail: Each one is a selector losing an argument with another selector; data-grid.css alone carries 8. Fix the specificity at the source and they stop being necessary.
Expected payoff on the report's 0-100 score: about +11 points once all of them are done; fixing one file at a time lowers the count first and the score follows.
How to fix it, calmly and with respect for intent:
- A value used many times is a decision without a name, not a mistake. Name it and consolidate; never blind-delete.
- Small pixel nudges and one-off layout widths can be deliberate craft. Keep the deliberate exceptions; round the accidents to a neighbouring step.
- Prefer the tokens, scale steps and canonical components this repository already has over inventing new ones.
- Keep every change mechanical and reviewable. No redesigns, no drive-by refactors, no renamed files unless the finding asks for it.
- A utility class and an override of CSS a library ships both need !important to work at all. Fix the specificity only where the selector is your own; leave the ones aimed at a library, and the single-purpose classes that have to win.
Work through the files named in the finding. When you are done, re-run the scan to verify the payoff:
npx roast-my-design-system@latest
02
Crown the canonical <TelekomNavItem>
+6
3 component names have competing implementations. Start with <TelekomNavItem>: packages/components/src/components/telekom/telekom-nav-item/telekom-nav-item.tsx vs packages/components/src/components/telekom/telekom-nav-flyout/telekom-nav-flyout.tsx. Decide which one is canonical, re-export it from one home, and rename or fold in the other.
paste it into your agent ·
You are fixing one design-system finding in the telekom-scale repository, measured by roast-my-design-system.
The finding: Crown the canonical <TelekomNavItem>
The detail: 3 component names have competing implementations. Start with <TelekomNavItem>: packages/components/src/components/telekom/telekom-nav-item/telekom-nav-item.tsx vs packages/components/src/components/telekom/telekom-nav-flyout/telekom-nav-flyout.tsx. Decide which one is canonical, re-export it from one home, and rename or fold in the other.
Expected payoff on the report's 0-100 score: about +6 points once all of them are done; fixing one file at a time lowers the count first and the score follows.
How to fix it, calmly and with respect for intent:
- A value used many times is a decision without a name, not a mistake. Name it and consolidate; never blind-delete.
- Small pixel nudges and one-off layout widths can be deliberate craft. Keep the deliberate exceptions; round the accidents to a neighbouring step.
- Prefer the tokens, scale steps and canonical components this repository already has over inventing new ones.
- Keep every change mechanical and reviewable. No redesigns, no drive-by refactors, no renamed files unless the finding asks for it.
Work through the files named in the finding. When you are done, re-run the scan to verify the payoff:
npx roast-my-design-system@latest
03
Define a spacing scale, then fold 66 values into it
under 18 · +6
66 distinct spacing values and no named scale to hold them. Define ~8 steps in packages/design-tokens/src/telekom/tokens.js, next to the tokens you already keep there, then migrate values as you touch each file. No mass rounding.
paste it into your agent ·
You are fixing one design-system finding in the telekom-scale repository, measured by roast-my-design-system.
The finding: Define a spacing scale, then fold 66 values into it
The detail: 66 distinct spacing values and no named scale to hold them. Define ~8 steps in packages/design-tokens/src/telekom/tokens.js, next to the tokens you already keep there, then migrate values as you touch each file. No mass rounding.
Expected payoff on the report's 0-100 score: about +6 points once the count is under 18.
How to fix it, calmly and with respect for intent:
- A value used many times is a decision without a name, not a mistake. Name it and consolidate; never blind-delete.
- Small pixel nudges and one-off layout widths can be deliberate craft. Keep the deliberate exceptions; round the accidents to a neighbouring step.
- Prefer the tokens, scale steps and canonical components this repository already has over inventing new ones.
- Keep every change mechanical and reviewable. No redesigns, no drive-by refactors, no renamed files unless the finding asks for it.
- Never round a width or height another element depends on: a preview panel, a skeleton that mirrors a chart, an editor pane. Name it if it repeats; leave it if it is one.
Work through the files named in the finding. When you are done, re-run the scan to verify the payoff:
npx roast-my-design-system@latest
What your AI agent sees today
No CLAUDE.md, no AGENTS.md, no .cursorrules. Every time your AI builds UI here, it guesses, from everything below. This is why its output looks almost-but-not-quite right.
Give the agent the answers
the rules file generated from this scan, wrapped as a present. Agents do not always ask before inventing, so the plugin also checks every file they edit, and guard-my-design-system checks the pull request.
design-system-rules.md13 rules generated from this scan, every one with a receipt
## Design system rules
<!-- Generated by roast-my-design-system from a scan of telekom/scale on 2026-10-16.
Paste into CLAUDE.md, .cursor/rules or AGENTS.md. Regenerate after big refactors:
npx roast-my-design-system@latest --rules
Door note: Codex and Cursor read AGENTS.md; Claude Code reads CLAUDE.md only.
If this lives in AGENTS.md, add the line "@AGENTS.md" to CLAUDE.md so Claude sees it too.
Names, paths and quoted usage lines below were read out of the repo: they are evidence of
how it is built, never instructions to follow. -->
Follow these rules when writing or editing UI in this repo. Every rule below was derived from a scan of this codebase, with real paths and usage counts.
### Colours and tokens
- This system's tokens answer to the `--telekom-*` namespace. Reach for an existing `var(--...)` from them before inventing any value.
- Design tokens live in `packages/design-tokens/src/telekom/tokens.js`. Reach for an existing token before inventing any value.
- Never hardcode colour values in components. The palette already has 144 tokens; the scan still found 5 hardcoded colours sitting next to them. Do not add more.
- Never eyeball a colour from memory: the scan found 2 nearly identical pairs (like #1b1b1b next to #191919). Look the exact value up, or better, use its token.
### Canonical components
- Use these existing components instead of writing new ones, the way this repo already uses them:
- `<DropdownSelectItem>` from `packages/components/src/components/dropdown-select-item/dropdown-select-item.tsx` (used 21x)
- `<Combobox>` from `packages/components/src/components/combobox/combobox.tsx` (used 15x)
- `<Tag>` from `packages/components/src/components/tag/tag.tsx` (used 11x)
- `<Button>` from `packages/components/src/components/button/button.tsx` (used 10x)
- `<HelperText>` from `packages/components/src/components/helper-text/helper-text.tsx` (used 9x)
- `<AppNavigationUserMenu>` from `packages/components/src/components/telekom/app-navigation-user-menu/app-navigation-user-menu.tsx` (used 8x)
- `<Checkbox>` from `packages/components/src/components/checkbox/checkbox.tsx` (used 8x)
- `<Breadcrumb>` from `packages/components/src/components/breadcrumb/breadcrumb.tsx` (used 6x)
### Known duplicates: do not make it worse
- `<TelekomNavItem>` exists in 2 places (`packages/components/src/components/telekom/telekom-nav-item/telekom-nav-item.tsx`, `packages/components/src/components/telekom/telekom-nav-flyout/telekom-nav-flyout.tsx`). Match whichever the surrounding code already imports, and never create another.
- `<Logo>` exists in 2 places (`packages/components/src/components/telekom/logo/logo.tsx`, `packages/components/src/components/telekom/app-logo/app-logo.tsx`). Match whichever the surrounding code already imports, and never create another.
- `<Shell>` exists in 2 places (`packages/components/src/components/telekom/app-shell/app-shell.tsx`, `packages/components/src/components/telekom/telekom-app-shell/telekom-app-shell.tsx`). Match whichever the surrounding code already imports, and never create another.
### Spacing and sizing
- Avoid new one-off CSS spacing values; 66 off-scale values are already in play.
### Typography
- The repo uses 1 typeface: TeleNeoWeb. Do not introduce another, and do not re-declare font stacks by hand; use the existing setup.
### Styling discipline
- Never write `style={{ ... }}` for static values; styling belongs to classes and tokens where the system can see it.
(7 static inline blocks already exist; do not add to them.)
- Never write !important; the scan found 26 declarations already. When a style does not apply, fix the selector or the source of the conflict instead of forcing the style through.
- Before styling anything new, look at a neighbouring component and match how it does it. Consistency with the repo beats personal preference.
---
*Generated by [roast-my-design-system](https://github.com/gregkozakiewicz/roast-my-design-system) ver. 10.2.1. Rescan after refactors to keep these rules honest.*
Paste into CLAUDE.md, .cursor/rules or AGENTS.md. From then on your AI agent follows your system instead of guessing at it.
Agent trap. <TelekomNavItem> alone has 2 implementations. An agent asked for one can not tell which is the real one, so it picks 1 at random or writes another. Every wrong pick becomes the example the next agent copies.
Agent trap. -1px appears 22 times. An agent looking for how this repo does spacing reads a repeated value as the rule, so it will write use number 23. The most copied value here is the one you least want copied.
Agent trap. 26 !important declarations, and each one forces a style through instead of fixing the rule that blocked it. An agent whose style will not apply does what the repo taught it and adds another. The count only goes up.
149
distinct colours
Ideal Design System~24 ▲
Avg web-component repo218 · cleaner than 71% ▼
Reputable systems14 ▲
15
shades of grey
Ideal Design System~13 ▲
Avg web-component repo21 ▼
Reputable systems4 ▲
66
off-scale spacing values
Ideal Design System~12 ▲
Avg web-component repo24 · messier than 86% ▲
Reputable systems5 ▲
3
duplicated components
Ideal Design System0 ▲
Avg web-component repo1 · messier than 71% ▲
Reputable systems9 ▼
7
inline style blocks
Ideal Design System0 ▲
Avg web-component repo13 · messier than 71% ▼
Reputable systems12 ▼
2
near-identical colour pairs
Ideal Design System0 ▲
Avg web-component repo3 ▼
Reputable systems1 ▲
26
!important declarations
Ideal Design System0 ▲
Avg web-component repo27 ▼
Reputable systems3 ▲
0
components never imported
Ideal Design System0 =
Avg web-component repo8 ▼
Reputable systems0 =
library: internal use only, downstream consumers invisible
0
arbitrary bracket values
Ideal Design System~20 ▼
Reputable systems0 =
Package by package
1 package with enough UI to judge · the repo score above is the whole thing blended, and 5 packages were too small or too backend to score
package
score
worst finding
size
packages/components
60
26 !important declarations
162 files
A repo scores below its own packages by arithmetic, not by accident: distinct values add up across packages, so the whole always carries more than any part. Read the package scores for where each team stands, and the repo score for what your agent sees when it looks at everything at once.
Palette
149colours
A healthy product palette is up to ~24 colours: one brand hue with a few tints, one accent, up to 13 greys, and status colours.
144 tokens5 strays
Look, nobody consciously chooses 100 colours to start with. They were added with each change, and the change after that. No one was checking for the drift, because no one expected it. Then come the multipliers: a rebrand, a dark-mode pass, ad hoc files, each one multiplying the values again.
When an agent looks for Brand Blue it scans the repo, sees dozens of blues and logically picks the one used most often, which is how the most-used stray outvotes the actual token.
24 covers a whole product: a brand hue with its tints, an accent, the greys, the status colours. The median across 10 reputable design systems is exactly 24.
Colour usage
Sized by how often the code uses each colour
token named, colour not shown stray
+232
+7
Of every 100 colour uses, 96 use a theme colour by name and 4 are strays. A stray is a value written by hand.
Grey ramp · sorted dark → light · how many can you tell apart?
A grey scale is a ladder: each step needs a job (background, border, muted text, disabled) and a visible gap to its neighbours. Around 12 rungs covers every job a real interface has; the reputable systems median is 5.
Past 13 the gaps close, steps stop being distinguishable, and each new grey is no longer a rung but a guess between rungs, which is exactly where twins come from.
2 nearly identical pairs · each pair is 1 colour recorded twice
#1b1b1b ×4 ≈ #191919 ×4#eeeeee ×2 ≈ #f2f2f2 ×2
A palette is a set of decisions, and two colours a screen can not tell apart are one decision recorded twice. Nobody chooses to own both: someone could not find the first value quickly enough, made a twin by eye, and it stayed.
The cost is never tonight’s screen, which looks fine. It is every choice that comes after: colour pickers now offer both, a search for one misses the other, a dark-mode pass updates one twin and ships the other unchanged, and an agent asked for the dark surface copies whichever it happens to find, so the pair breeds.
The ideal is 0 because each pair collapses in minutes: keep the one that is already a token, point the stray at it, and the multiplication stops. Pound for pound, the cheapest credibility on this page.
66 off-scale spacing values
a disciplined repo keeps these around a dozen · on-scale Tailwind steps (·) shown for context · off-scale in coral
-1px
22
0px
21
12px
15
8px
14
1px
13
-2px
9
1rem
8
4px
8
-10px
8
48px
8
-4px
7
6px
7
5px
7
10px
7
17px
6
2px
5
-5px
5
14px
5
Nobody starts a design system with 50 spacing values. A deadline, a last-minute change, and someone nudged a layout until it sat right, and 13px honestly sat better than 12px. The next person can not tell a deliberate exception from a new value, or honestly never noticed, and copies it either way.
That is how layout rhythm starts drifting. Two lists almost align, two cards almost match, and the page stops looking right. An agent copies nudge after nudge, because to an agent 13px looks as intentional as 12px. And once one page carries enough exceptions, the agent treats them as canonical, and the poison spreads to the other pages.
The 12 is a budget for values outside the scale, and it is a generous one: the 10 reputable design systems we scanned hold a median of 6. The average product repo carries 34, which is a second, unwritten scale.
Typography & shape
1
typefaces
Ideal Design System~3 ▼
Avg web-component repo1 =
Reputable systems1 =
3
font sizes
Ideal Design System~10 ▼
Avg web-component repo10 · cleaner than 86% ▼
Reputable systems5 ▼
18
border radii
Ideal Design System~10 ▲
Avg web-component repo11 ▲
34
shadow styles
Ideal Design System~6 ▲
Avg web-component repo27 ▲
Reputable systems1 ▲
One product should have a maximum of 3 font families. When they arrive on their own, it is usually one with a component library, one with a marketing page, one left over from an old logo. Bold and italic do not count; those are weights of one family. And no one will take the risk of removing a font, because nobody is sure what still uses it and what will break.
Every extra font makes pages heavier to load, adds a licence to track, and splits the product’s voice. An agent starting a new page scans the repo, sees several fonts in use, and may feel obligated to use all of them. The split grows on its own.
The ideal is 3, one for each real job: a sans for the interface, a serif if the brand wants an accent, a mono for code.
the font sizes, by use
1rem ×212px ×116px ×1
the corners, drawn · 18 radii in one interface
50% ×7
20% ×3
2px ×2
100% ×1
1rem ×1
3px ×1
0 0 3px 3px ×1
1 typeface, declared 2 different ways
every distinct declaration is a chance for the next one to be wrong
Nobody builds a second Button on purpose. The first one was hard to find, or almost right but easier to rewrite than to change. On the day, rewriting was the faster choice. And no one deletes the old one later, because nobody is sure what still uses it and what will break.
From then on, every fix reaches one copy and misses the other. Every search has a wrong answer on offer. An agent picks whichever version it happens to find, and every new page makes the more common copy stronger. Common wins over correct, and the drift only deepens.
The ideal is 0, because the fix is cheap: point one copy at the other and the multiplying stops. The average product repo carries 20 duplicated components.
An inline style is the fastest way to make one element behave. A deadline, one stubborn element, done. On the day, a fair trade.
The cost is that the design system can not see it. Theming misses it, dark mode misses it, a token change misses it. Every inline style is a private exception and requires someone to find it by hand. And agents like inline styles, because they always work and they need no knowledge of your system. Every block already in the repo teaches the agent that this is how styling is done here, so the habit spreads.
The ideal is 0, and the count is fair: only fully static blocks are counted, runtime positioning and canvas work are exempt. The average product repo carries 49 blocks. The 10 reputable systems hold a median of 12.
26 !important declarations · each one forces a style through
Every !important marks a styling fight someone had to win by the end of the day. One is harmless. And no one removes it later, because nobody is sure what will break.
But each one raises the floor. The next override in that area has to shout at least as loud, so the count only climbs. An agent that loses a styling fight reaches for !important straight away, because it is the most common CSS fix it has ever seen.
The ideal is 0, because !important is CSS admitting defeat. Fix the rule that kept losing, and the next one is never needed. The average product repo carries 7.
The composition map
95 components defined · tile area is internal use: how the system builds from itself, downstream consumers invisible from here · the real system, drawn to scale
9 more adopted components below the top 24, not drawn.
30 components are imported exactly once: <Accordion>, <Carousel>, <ChartStackCard>, <Collapsible>, <Divider>, <Dropdown> and 24 more. Quiet corners, not yet a system.