All Insights
adoptionJul 2026GDS team4 min readInsight

A practical adoption playbook

Theme first, freeze sprawl, win the shell, then migrate high-traffic seams - a step-by-step path without a big-bang rewrite.

Adopting GDS is not a weekend rewrite. Most Granicus frontends already ship with another UI kit - Chakra UI, Material UI, Ant Design, or a mix. The goal is to converge over time: put the theme in place, win the highest-traffic seams, then retire legacy UI islands when they stop earning their keep.

This playbook is the path we recommend for apps like Admin UI, Blue Haven, Bazaar, and other EHQ (or Granicus) frontends.

Principles

  1. Ship value continuously - migration work should ride alongside product delivery, not freeze it.
  2. Theme before components - get tokens and GDSThemeProvider in early so new work looks right even before every control is swapped.
  3. Migrate by seam, not by folder - replace UI at natural boundaries (shell, forms, dialogs), not “all of src/components this sprint.”
  4. One system going forward - new screens default to GDS; legacy kits shrink on purpose.
  5. Design and code move together - use Figma SPECS + Gds* names so prototypes and PRs speak the same language.

Phase 0 - Align the team

Before installing a package, agree on the basics:

DecisionWhy it matters
OwnerWho answers “use GDS or legacy?” for this repo
Success metricse.g. % of new PRs on GDS, critical flows migrated
Non-goalsWhat you will not rewrite in the first quarter
Design contactWho maintains Figma SPECS usage for the squad

Publish a short RFC or Confluence note. Ambiguity is what keeps both Chakra and MUI growing in the same app forever.

Phase 1 - Install and theme

Follow Getting started: Artifactory auth, @granicus/gds-core, peers, and GDSThemeProvider.

Checklist:

  • App root (or feature shell) wrapped in GDSThemeProvider
  • CssBaseline (or equivalent) so typography and surfaces reset cleanly
  • Light/dark strategy decided (system, user toggle, or product default)
  • Engineers know to import Gds* from @granicus/gds-core/..., not raw @mui/material for new UI

Done when: a throwaway screen (or Storybook-in-app sandbox) renders a GdsButton and GdsTextField with correct Granicus tokens.

Phase 2 - Freeze the sprawl

Stop the bleeding before you migrate history:

  • New features use GDS by default
  • No new dependency on an alternate UI kit for net-new screens
  • Exceptions require a short written reason (timeline, missing component)

This phase is mostly process. It is also where you get the biggest ROI: every week of new Chakra/Ant UI is another week of dual maintenance.

Phase 3 - Win the shell

Migrate the chrome users see on every visit:

  • App bar / side nav / page headers
  • Primary buttons and icon buttons in the shell
  • Global feedback (toasts, banners, dialogs used for confirmations)

Why shell first? One successful swap teaches the team the patterns and makes the product feel like GDS immediately - even if deep feature pages still use legacy controls.

Phase 4 - High-traffic components

Pick the controls that appear in almost every flow:

  1. Buttons - primary, secondary, destructive
  2. Text fields & selects - search, filters, forms
  3. Dialogs & alerts - confirms, errors, empty states
  4. Tabs, chips, tables - list and admin-heavy UIs

For each family:

  1. Map legacy usage → matching Gds* component (Components)
  2. Swap in one vertical slice (one form, one settings page)
  3. Fix spacing/tokens, then expand horizontally

Prefer strangler PRs: old and new can coexist behind a clear import boundary. Avoid mega-PRs that touch 80 files.

Phase 5 - Forms and complex flows

Forms are where libraries diverge most. Approach them deliberately:

  • Rebuild new forms on GDS form primitives
  • Migrate existing forms when you already touch that flow for product work
  • Keep validation and data logic; replace only the presentation layer when possible

If a flow is scheduled for redesign, migrate UI in that redesign - do not migrate twice.

Phase 6 - Retire legacy UI kits

Only after coverage is real:

  1. Inventory remaining Chakra / MUI / Ant / custom islands
  2. Tag each: migrate, wrap, or delete (dead UI)
  3. Remove unused theme providers and global CSS from the old kit
  4. Drop the dependency when imports hit zero

Celebrate dependency removal in release notes - it is the clearest signal that adoption stuck.

Suggested sequencing for an EHQ-style repo

Week 1-2     Theme + freeze sprawl + shell pilot
Week 3-6     Buttons, fields, dialogs on 1-2 critical journeys
Month 2-3    Expand to lists/tables/filters; migrate on product touch
Ongoing      Retire legacy kit; track % GDS in new PRs

Adjust for team size. A smaller squad should stay ruthless about shell + one journey before widening.

Anti-patterns to avoid

Anti-patternBetter approach
Big-bang rewrite branchSeam-by-seam strangler
Wrapping every legacy component foreverPrefer real Gds* swaps for shared primitives
Mixing three kits on one new screenOne system per screen going forward
Migrating without designUse Figma SPECS; open a design thread when a pattern is missing
“We’ll migrate when GDS is complete”Adopt what exists; request gaps via the GDS / design team

When a component is missing

Do not invent a second design system in your repo.

  1. Check Components and Storybook
  2. Check Figma SPECS for an existing pattern
  3. Open a request with the GDS / design team
  4. If you must ship now, isolate a temporary local control and schedule the GDS replacement

How you know it is working

Useful signals:

  • New PRs default to Gds* imports
  • Shell and top journeys match Figma SPECS
  • Legacy UI kit bundle size / import count trends down
  • Design review comments shift from “wrong button” to product questions