ADG/REI Systems
2022 - 2025
Shipped & ongoing
Earning the seat, then moving a federal platform off AngularJS
I led the design side of a move from AngularJS to React on one internal federal application. The code was not the hard part. Trust was.
Role
Timeline
Scop
Platform
Overview
I could not migrate a platform until people trusted design enough to invite us in.
Federal staff used one internal application to document cases and move them through a long, form heavy process. People at the end were waiting on a decision about their lives. Where the system failed, work went back to paper.
The app ran on AngularJS, which was no longer supported, with an old design system that had grown one request at a time.
I led the design side of the move to React. The hard part was never the code. Trust had been spent before I arrived, and product owners and technical leads were wary of anyone who said โdesign.โ
Three questions guide this work
01
Can staff get through a case without going back to paper?
02
Can teams build from one trusted set of parts?
03
Can the system keep going without me?
What has changed so far
50+
Reusable components, 47 at WCAG AA
Counted
โ40%
Shorter engineering implementation cycles
Benchmark
โ50%
Fewer visual regressions across 15+ teams
Benchmark
Stakes
The people on the other side of the screen were doing important work with broken tools.
01
Friction
Paper kept winning.
When the system failed, people worked around it.
02
Friction
An unsupported framework.
AngularJS was no longer supported, and every fix added weight.
03
Friction
A system grown one request at a time.
The old design system had no shared rules left.
Confidentiality Note
Not every part of this is mine to share, so I kept the agency and the case details general on purpose.
Before state ยท where the digital flow broke
01
Start case
โ
02
Gather details
โณ Back to paper
โ
03
Review
โ
04
Resolve gaps
โณ Back to paper
โ
05
Decision
Evidence
I went to where the work happens.
I traveled to multiple sites around the country, interviewed the people who use the application every day, and mapped their full workflow from start to finish.
01
Visit the sites
->
02
Interview users
->
03
Map the workflow
01
Can staff get through a case without going back to paper?
02
Can teams build from one trusted set of parts?
03
Can the system keep going without me?
How solid is this?
The conversations
Observed
Direct conversations at multiple sites, not a formal study.
The workflow maps
Observed
Drawn by me and checked with the people who do the work.
The impact
Estimated
Rounded from internal analytics.
Generalized end to end workflow
Staff
Open case
Collect
Review
Decide
System
Create
Validate
Route
Close
Paper
Pain point 1
Pain point 2
I turned evidence into a migration sequence.
The work stayed traceable from field signal to product decision to system effect.
Signal from the work
Design move
What it changed upstream
01
Paper appeared when the digital flow broke.
โ
Map the whole case, not one screen.
โ
Sequence the migration around workflow breaks.
02
Teams rebuilt similar patterns in different ways.
โ
Turn repeated work into shared components.
โ
Give the application kit one trusted base.
03
Partners were wary of another design-led promise.
โ
Join the work and close useful gaps.
โ
Make shared governance feel ordinary.
Decision
Nobody gave us a seat, so we kept showing up until it became ordinary.
01
Wait to be invited.
Safe, and nothing changes while we wait.
02
Ask leadership for a mandate.
Fast on paper. People follow a mandate carefully and own it never.
03
Chosen
Show up, be useful, repeat.
Slow, and it works.
The tradeoff was on purpose
This looks less like a plan at first. There is no launch and no big reveal. But every win came from showing up and being useful before anyone asked.
How it compounded
Small, practical help became trust. Trust became access. Access became a better platform.
01
Make the case
Our design lead held countless one on ones to include us.
02
Show up
We joined meetings that were not ours, sometimes just to listen.
03
Close a gap
A missing spec, a mapping nobody owned, so we took every chance.
04
Become the habit
Product owners started bringing us in early without being asked.
What changed
The lead product owner began treating me as a strategic partner on how to move forward with the migration.
Solution
One application, and a design lifecycle that never stopped.
We did not design the future in one go. We took snapshots of the current state, picked the low hanging fruit, shipped it, and took another. A cross functional tiger team of leads set priorities, and there was politics to navigate along the way.
A loop, not a launch
1
Snapshot
โ
2
Prioritize
โ
3
Ship
Then look again
One table, five perspectives
Priorities for the app and the design system
Design
Engineering
Product
QA
Accessibility
The principal-level move
A component swap would have been easier to explain. It would not have fixed the system.
Not enough
Repaint the old screen
The same workflow problems survive under cleaner components.
โ
What changed
Start with the work
Use workflow breaks to decide what earns a place in the migration.
โ
How it scales
Codify the answer
Turn a solved product problem into a reusable pattern and shared rule.
Generalized Visuals
What changed at component level
These are redrawn examples, not real federal screens. They show the design logic without exposing the agency, product, or case data.
Generalized component example
Actions gained a clear hierarchy.
Problem:
Every action competed at the same volume, so the next step was hard to scan.
Design response:
Give primary, secondary, and quiet actions distinct jobs, then make focus visible.
Before
Continue
Save
Cancel
โ
After
Continue
Save
Cancel
One obvious next step
Visible keyboard focus
Destructive actions stay distinct
Generalized component example
Dense tables became easier to read.
Problem:
Heavy grids made every cell feel equally important and status was buried in text.
Design response:
Reduce visual noise, open the spacing, and let labeled status markers carry meaning.
Before
Case
Status
Action
Case 018
In review
View
Case 024
Needs info
View
โ
After
Case
โ
Status
Action
Case 018
In review
View
Case 024
Needs info
View
Faster visual scanning
Status uses text and shape
Rows have a clear action
Generalized component example
Forms started helping before people got stuck.
Problem:
Labels, focus, and errors did not explain what happened or how to recover.
Design response:
Pair persistent labels with contextual help, visible focus, and errors that say what to do.
Before
Case category
Select a category
What happened?
Add a short description
โ
After
Case category
Select a category
What happened?
Add a short description
This helps the next reviewer understand the case.
Errors explain recovery
Labels stay attached
Focus follows reading order
Three states, built for the whole journey
Rebuilt
A clearer default
The focus order follows the reading order.
error
Tell us what happened before continuing.
An error that helps
The error is announced to a screen reader.
empty
No case notes yet
Add the first note when you are ready.
An empty state with a next step
Text and controls meet 4.5:1 contrast.
System
Two levels of governance, so teams moved fast without drifting.
Level 1
Design system Storybook
Generic building blocks every product can use.
->
Level 2
Application Storybook kit
Components, patterns and layouts ready for this applicationโs real work.
->
Level 3
15+ product teams
Build from the kit while change flows one way from the base.
Built for real use
Production, not a picture of production.
50+ reusable components mapped to production code. 47 at WCAG AA, tested with keyboard and screen reader.
Handoff, replaced
We wrote the contract together.
Component specs were written with engineers. My design systems partner led the token work, and we supported each other on nearly everything.
Deep dive
How the tokens connect
+
Results
Here is what I can count, and what I can estimate.
Fewer visual regressions across 15+ teams
โ50%
Estimated
Shorter engineering implementation cycles
โ40%
Estimated
Less rework
โ25%
Estimated
Better task completion
โ15%
Estimated
50+
Reusable components
47 at WCAG AA
Counted
Internal analytics, rounded. Exact figures withheld because this is federal work.
What I canโt claim
A single dollar figure for this work.
Reflection
A migration is a trust project with a code project inside it.
01
What Iโd do differently.
Trust came from being in the room, in meetings that were not ours and in countless one on ones led by our design lead. Next time I would start that work on day one and plan it like a real workstream, not something that happens on the side.
02
What surprised me.
How little of this was technical. I expected the hard part to be the code. The hard part was earning trust from people who had been burned by a design agency before us. Sometimes sitting quietly in a meeting and just listening was the work.
03
What I do in week two now.
I find out who got burned before me, and I go to their meetings. Then I look for one small gap nobody owns and close it. It is a small act, and it is how the invitation starts.
Keep Reading
ADG/REI Systems
Shipped
Refining CSS variables, so one design system could scale
Our CSS had grown one request at a time, so the same color lived in many places. We rebuilt it as three tiers of tokens that design and engineering could share. My design systems partner led the effort, and I worked beside them.
Role
Design systems specialist
Timeline
Needs input ยท [Years]
Scope
One federal application,
Needs input ยท [Number of teams, 15+ or 30+]
Platform
Internal enterprise casework application

Primitive
Semantic
Component
Illustrative, generalized
Components / Button
Default
Button
Hover
Button
Focus
Button
--ds-primitive-blue-500
--ds-color-action-primary-bg
--_bg
local to the Button
.ds-button {
--_bg: var(--ds-color-action-primary-bg);
background: var(--_bg);
border-radius: var(--ds-radius-md);
padding: var(--ds-spacing-sm) var(--ds-spacing-lg);
}
--ds-color-focus-ring
Overview
A design system cannot scale when every team spells the same color differently.
The application carried years of CSS written one request at a time. Colors, spacing and type were hardcoded in many places, so a small change meant a long hunt through stylesheets.
A move to React and Tailwind was coming. It needed one source of truth that design and engineering could both trust. A design audit showed we could not scale without one.
My design systems partner led this effort. I worked beside them on
Needs input ยท [What I owned, in one line]
.
Three questions guide this work
01
Can design and engineering use the same name for the same thing?
02
Can a theme change without touching every component?
03
Can a team add a new token without breaking the rest?
3
Tiers of tokens: primitive, semantic, component
Counted
โ50%
Fewer styling defects in quality assurance (QA)
~
Estimated
Needs input ยท [How this was measured]
Needs input ยท [Teams using the tokens]
Product teams using the tokens
Needs input ยท [What "using" means, and whether 100% adoption is true]
Rounded estimates. Exact figures withheld because this is federal work.
Hardcoded CSS felt fast on day one and expensive on day one hundred.
01
Friction
Many spellings of one color.
The same color appeared in slightly different values across stylesheets.
02
Friction
Design and code used different names.
Figma and code did not share a vocabulary, so every handoff needed translating.
03
Friction
A framework move was coming.
Moving from AngularJS to React meant every style had to move too, and scattered CSS would arrive scattered.
Needs input ยท [Confirm these three frictions match what you saw]
One color, spelled six ways
#2353D9
Button
#2455DA
Link
#2A57D8
Header
#2250D6
Tag
#2656DB
Chart
#2152D8
Banner
Six blues that look the same and are not. Illustrative, redrawn example, not real federal code.
Needs input ยท [How many variants the audit really found]
Not every part of this is mine to share, so I kept the agency and the case details general on purpose.
I audited before I trusted anything.
A design audit came first. Before naming a single token, we listed what the stylesheets really used: colors, spacing, type and radii, and where each one showed up.
Needs input ยท [Number of unique values found, rounded]
Needs input ยท [Number of stylesheets or components reviewed]
1
Inventory the values.
2
Group the duplicates.
3
Name the jobs.
01
Many values, few real decisions.
02
The same job was done by different values.
03
Names described looks, not jobs. For example "blue" instead of "primary action."
Many values became a few jobs
Raw values
โ
Jobs they were doing
โ
Three tiers
Illustrative. Real counts are withheld. The shape is the point.
How solid is this?
The audit findings.
Observed
What my partner and I found in the stylesheets. Not a formal study.
The defect change.
~
Estimated
A rounded estimate of fewer styling defects in quality assurance.
The adoption.
Needs input ยท [Source and definition]
We could document the mess, flatten it, or give it three tiers.
Needs input ยท [Confirm these were the real options]
01
Document the CSS we had.
Cheapest to start. The drift stays, and the docs go stale.
02
One flat list of variables.
Easy to learn. A new theme still touches every component.
03
Chosen
Chosen. Three tiers: primitive, semantic, component.
More naming discipline up front. A theme changes in one place and components never change.
The tradeoff was on purpose.
Three tiers ask more of people at the start. Names have jobs, and not every value earns a token. We accepted more rules to teach and follow, because a system that could change in one place was worth it.
Gained: change a theme or a brand in one place.
Accepted: more naming rules to teach and follow.
How teams adopted it.
01
Name it together.
02
Show a working component.
03
Move one component at a time.
04
Make it the default.
Needs input ยท [Draft, replace each step with what really happened]
From scattered values to a system, in six steps.
01
Audit the CSS.
โ
02
Name tokens by their job.
โ
03
Map them to Tailwind.
04
Move components one at a time.
โ
05
Check before shipping.
โ
06
Keep the rules in the system.
Needs input ยท [Draft, confirm each step]
Same button, two spellings
Before
background: #2455DA;
the value is typed straight into the component
โ
After
background: var(--_bg);
the component asks the system
--ds-primitive-blue-500
โ
--ds-color-action-primary-bg
โ
--_bg
Redrawn example, not real federal code.
One state, checked two ways
Default
Button
Focus
Button
Focus ring is visible against the page and the fill.
Label text meets 4.5:1.
The same button is shown in its default and keyboard focus states. The focus state has a visible two pixel ring, and both labels meet the Web Content Accessibility Guidelines (WCAG) text contrast minimum.
Error
Token check failed.
Fix the contrast before this change can merge.
Illustrative
Empty
No token changes to review.
The system is up to date.
Illustrative
Three tiers, so a theme changes in one place and components never change.
Tier 1
Primitive
Raw values like --ds-primitive-blue-500. A rebrand changes these.
โ
Tier 2
Semantic
Names a job, like --ds-color-action-primary-bg. A new theme, such as Light and Dark, changes these.
โ
Tier 3
Component
Local names, like --_bg inside the Button, that only point to semantic tokens. These never change.
Primitive values feed semantic jobs. Semantic jobs feed local component aliases.
Two levels of governance.
A base design system Storybook holds the tokens. An application Storybook kit is built from it and uses them.
How names are chosen.
One simple pattern, category then role then state, like color-action-primary-bg-hover.
Illustrative
Deep dive
A small version you can open.
I rebuilt the idea as a small public example. Figma variables export to JSON, a script builds CSS variables, and Storybook shows a Button and a chart. A build check blocks the merge if contrast fails.
Light and Dark
3 tiers
38 checks
WCAG contrast
Personal example, not federal work. Sample data is illustrative.
I used Claude to scaffold the code and the Figma file. I made the design decisions and checked the results.
Open the repo
github.com/jc575/design-token-pipeline
Here is what I can count, and what I can estimate.
Tiers of tokens
3
Counted
Fewer styling defects in quality assurance (QA)
about 50%
~
Estimated
Product teams using the tokens
Needs input ยท [Number and definition]
From the small version.
Counted
Personal example.
A focus ring measured 2.82:1 against the primary button fill, under the 3:1 minimum. The build check caught it. After the fix it measures 3.78:1.
38 automated checks pass, 19 in Light and 19 in Dark.
Every checked pair clears its minimum, and two clear it narrowly.
0
6
12
18
Text on page
16.90
Secondary text on surface
7.19
Secondary button text on its fill
8.87
Danger button text on its fill
5.62
Primary button text on its fill
4.75
Margin 0.25
Focus ring on primary fill
3.78
Focus ring on danger fill
3.20
Margin 0.20
Severity, medium step, on surface
3.29
Source: the check script in the open example, Light mode, 18 pairs per mode.
Read this as text
Counted
Text on page: 16.90 against a minimum of 4.5.
Secondary text on surface: 7.19 against a minimum of 4.5.
Secondary button text on its fill: 8.87 against a minimum of 4.5.
Danger button text on its fill: 5.62 against a minimum of 4.5.
Primary button text on its fill: 4.75 against a minimum of 4.5. Margin 0.25.
Focus ring on primary fill: 3.78 against a minimum of 3.
Focus ring on danger fill: 3.20 against a minimum of 3. Margin 0.20.
Severity, medium step, on surface: 3.29 against a minimum of 2.
What I can't claim
Leading this effort. My design systems partner did. And a single dollar figure for this work.
Needs input ยท [Confirm]
A token system is a naming project with a code project inside it.
01
What I'd do differently.
Needs input ยท [My real answer]
02
What surprised me.
Needs input ยท [My real answer]
03
The name I'd change first.
Needs input ยท [My real answer]
Keep reading

Illustrative, generalized
Components / Button
Default
Button
Hover
Button
Focus
Button
--ds-primitive-blue-500
--ds-color-action-primary-bg
--_bg
local to the Button
.ds-button {
--_bg: var(--ds-color-action-primary-bg);
background: var(--_bg);
border-radius: var(--ds-radius-md);
padding: var(--ds-spacing-sm) var(--ds-spacing-lg);
}
Earning the seat, then moving a federal platform off AngularJS.
ADG/REI Systems

Illustrative, generalized
Components / Button
Default
Button
Hover
Button
Focus
Button
--ds-primitive-blue-500
--ds-color-action-primary-bg
--_bg
local to the Button
.ds-button {
--_bg: var(--ds-color-action-primary-bg);
background: var(--_bg);
border-radius: var(--ds-radius-md);
padding: var(--ds-spacing-sm) var(--ds-spacing-lg);
}
Many tools, one standard teams want to use.
Fidelity
Back to top
