gd-design-library
v1.8.2
Published

Readme
GridKit – Grid Dynamics Design System

GridKit is the official design system and component library from Grid Dynamics.
It provides a set of reusable, accessible, and themeable React UI components designed to accelerate the development of consistent, scalable applications – with a focus on e-commerce and enterprise platforms.
✨ Features
- 🧩 64 modular components (atoms, molecules, organisms, layout)
- 🎨 Theming support with dynamic runtime switching
- 🔗 Design tokens synced with Figma
- 📦 Optimized build using Vite
- 📚 Fully documented via Storybook
- ♿ WCAG 2.1 AA-compliant components
- ⚙️ Type-safe and fully tested with Vitest + RTL
- 🤖 Built-in AI integration — LLM → React/TSX code generation or A2UI JSON spec rendering
- 🔄 A2UI mode: LLMs generate structured JSON specs validated against
ui-specification-schema.json, rendered at runtime byrenderA2UISpecwith zero custom JSX - 🎯
buildA2UISystemPromptkeeps LLM instructions in sync with the live component map — no manual prompt maintenance - 🔌 Action system: define
A2UIActionDefinition[]once, share betweenbuildA2UISystemPrompt(LLM constraint) andrenderA2UISpec(runtime handler wiring)
📦 Installation
Start by ensuring that you already have @emotion/react and @emotion/styled installed. Then, run one of the following commands to install the dependencies:
npm install gd-design-library @emotion/styled @emotion/react
# or
yarn add gd-design-library @emotion/styled @emotion/react🧑💻 Getting Started
Prerequisites
- Node.js (22.17.0 or higher)
- Yarn or npm
Clone & Install
git clone https://github.com/griddynamics/cto-rnd-system-design.git
cd gd-design-system
yarn install🚀 Development
Start the local dev server with Vite:
yarn devOpen http://localhost:5173 in your browser.
Run Storybook
yarn storybook🏗️ Project Structure
gd-design-system/
├── src/
│ ├── components/
│ │ ├── atoms/ # 21 basic building blocks (Button, Input, etc.)
│ │ ├── molecules/ # 18 simple combinations (Accordion, Table, etc.)
│ │ ├── organisms/ # 10 complex sections (Card, Chart, Modal, etc.)
│ │ └── layout/ # 6 structural components (Row, Column, FlexContainer, etc.)
│ ├── ai/ # AI integration system (code mode + A2UI mode)
│ ├── tokens/ # Design tokens from Figma
│ ├── hooks/ # Shared React hooks
│ └── utils/ # Utility functions
├── .storybook/ # Storybook config
├── vite.config.ts # Vite config
├── tsconfig.json # TypeScript config
├── README.md🧪 Testing & Linting
Run Tests
yarn testLint Code
yarn lintFormat Code
yarn formatCheck Formatting
yarn format:check🔍 Build Verification
GridKit ships a 5-phase verification pipeline that runs automatically after every yarn build:ui. It checks that the published package works correctly for all consumers — ESM, CJS, SSR, and tree-shaking.
Commands
| Command | What it does |
| ---------------- | --------------------------------------------------------------------- |
| yarn build:ui | Full build → phases 1–5 → summary |
| yarn verify:ui | Phases 1–5 + summary, skips rebuild — use after an existing build |
| yarn view:ui | Generates report.html from JSON reports and opens it in the browser |
yarn build:ui runs in order: readme stats check → AI docs generation → type-check → lint → Vite build → all 5 phases → combined terminal summary.
yarn view:ui can be run any time after yarn verify:ui (or yarn build:ui) has written JSON reports to libs/ui/scripts/output/. It opens a dark-theme HTML dashboard with charts and tables for every phase — no server needed.
Visual dashboard
yarn verify:ui && yarn view:ui
# or after a full build:
yarn build:ui && yarn view:uiThe dashboard (libs/ui/scripts/output/report.html) includes:
- Overview — totals banner, 5 phase status cards, summary charts
- Phase 1 — exports by category (donut), dependency status (pie), warnings table
- Phase 2 — violations list, per-component KB footprint bar chart (yellow = cross-component deps)
- Phase 3 — errors with full publint issue list, warnings by type (pie), circular deps breakdown
- Phase 4 — RSC readiness donut, browser globals by context (pie), unguarded globals table (file · line · global · context)
- Phase 5 — CJS errors and warnings
To generate without opening: node libs/ui/scripts/view-reports.mjs --no-open
What each phase checks
| Phase | Script | Checks |
| -------------------- | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1 · Public API Audit | audit-api.mjs | All exported symbols traceable from src/index.ts; undeclared / unused / bundled deps; exports gap in package.json |
| 2 · Tree-Shaking | treeshake-check.mjs | Import graph built from dist/; cross-component contamination per probe; sideEffects field; per-component KB footprint |
| 3 · Build Lint | build-lint.mjs | Circular imports (structural vs barrel); package.json exports validity; .d.ts completeness; private/internal leaks; "use client" consistency; publint standards check |
| 4 · SSR Safety | ssr-check.mjs | Node.js import() test; unguarded browser globals; RSC "use client" coverage; Emotion SSR guidance |
| 5 · CJS Verification | cjs-check.mjs | .cjs output exists; require() works in Node.js; exports map has "require" conditions; .cjs uses CommonJS syntax; "main" field points to CJS |
Terminal summary
After all phases run, a combined table is printed:
╔══════════════════════════════════════════════════╗
║ gd-design-library · Build Verify Summary ║
╚══════════════════════════════════════════════════╝
Phase 1 ✓ Public API Audit 142 exports · 0 warnings
Phase 2 ✓ Tree-Shaking Check 0 violations
Phase 3 ⚠ Build Lint 0 errors · 3 warnings
Phase 4 ✓ SSR Safety Check 0 errors · 0 warnings
Phase 5 ✗ CJS Verification 1 errors · 0 warnings
── Totals ──────────────────────────────────────────
Errors : 1
Warnings : 3
Violations : 0Status icons: ✓ pass · ⚠ warnings only · ✗ errors · – report not found (phase was not run).
Investigating failures
Visual dashboard — easiest way to explore all phases at once:
yarn view:uiRun a phase directly — full console output with file paths and line numbers:
node libs/ui/scripts/treeshake-check.mjs # Phase 2
node libs/ui/scripts/build-lint.mjs # Phase 3
node libs/ui/scripts/ssr-check.mjs # Phase 4
# --verbose for full import chains / all global usages:
node libs/ui/scripts/treeshake-check.mjs --verbose
node libs/ui/scripts/ssr-check.mjs --verboseOr via nx:
nx run ui:treeshake-check
nx run ui:build-lint
nx run ui:ssr-checkRead the JSON report directly — already written by yarn verify:ui:
cat libs/ui/scripts/output/treeshake-report.json # Phase 2 — "violations"
cat libs/ui/scripts/output/build-lint-report.json # Phase 3 — "errors", "warnings"
cat libs/ui/scripts/output/ssr-report.json # Phase 4 — "errors", "warnings"JSON reports
Each phase writes to libs/ui/scripts/output/:
| File | Phase | Key fields |
| ------------------------ | ----- | ----------------------------------------------------------- |
| public-api-map.json | 1 | totalExports, byCategory, exports |
| deps-map.json | 1 | analysis.undeclared, analysis.unusedDeps, warnings |
| treeshake-report.json | 2 | violations, probes, buildFormats |
| build-lint-report.json | 3 | errors, warnings, circularDeps |
| ssr-report.json | 4 | errors, warnings, nodeImport, browserGlobals, rsc |
| cjs-report.json | 5 | errors, warnings |
| report.html | all | visual dashboard generated by yarn view:ui |
CI usage
Use nx run ui:verify for CI — runs all 5 phases with --check (exits 1 on any error) and --json:
nx run ui:verifyIndividual phase targets:
nx run ui:audit-api # Phase 1
nx run ui:treeshake-check # Phase 2
nx run ui:build-lint # Phase 3
nx run ui:ssr-check # Phase 4
nx run ui:cjs-check # Phase 5
nx run ui:view-reports # open dashboard (reads existing JSON reports)🧰 Component Generator
Use our CLI script to quickly scaffold new components:
Add Execution Permission (first time)
chmod +x ./bin/create-component.jsCreate a Component
yarn crc ButtonGroupYou’ll be prompted to select:
coredomainSpecific
The script will generate boilerplate files and update exports automatically.
🧩 Usage
Wrap your app in the ThemeProvider with isDefault to apply default GD global styles and tokens:
import { ThemeProvider } from 'gd-design-library';
// OPTIONAL: default GD global styles, reset, font.
import 'gd-design-library/styles.css';
function App() {
return (
<ThemeProvider isDefault>
<YourAppRoutes />
</ThemeProvider>
);
}or initialTheme to install custom one as default initially
{
"name": "myCustomTheme",
"componentAStyles": {
"style": "value"
}
}import { ThemeProvider, defaultTheme } from 'gd-design-library';
import myCustomTheme from 'PROJECT_PATH/myCustomTheme'; // JSON or any js/ts and similliar with object return
const App = () => {
// In case you want extend default theme, by overwriting only particular components
const initialTheme = Object.assign({}, defaultTheme, myCustomTheme);
return (
<ThemeProvider initialTheme={initialTheme}>
<YourAppRoutes />
</ThemeProvider>
);
};You can now use components like this:
import { Button } from 'gd-design-library';
<Button variant="primary">Click me</Button>;Adding new theme
Here’s a minimal React app example showing how to create and apply custom theme based on default, exactly like in your snippet. Example structure:
main.tsx: wraps the app withThemeProvider
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { ThemeProvider } from 'gd-design-library';
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<ThemeProvider isDefault>
<App />
</ThemeProvider>
</React.StrictMode>
);useCustomTheme.tsx: theme hook
** Can be used on top level instead isDefault, use initialTheme, based on updateThemeTokens & defaultTheme from hook snippet
import { useEffect } from 'react';
import { updateThemeTokens, defaultTheme, useTheme } from 'gd-design-library';
export default function useCustomTheme() {
const { addTheme, setTheme } = useTheme();
const customTheme = {
...defaultTheme,
name: 'CustomTheme',
};
useEffect(() => {
// Customise tokens
updateThemeTokens(customTheme, {
'select.dropdown': {
backgroundColor: 'red',
borderRadius: '10px',
boxShadow: '0 0 10px rgba(0, 0, 0, 0.1)',
padding: '10px',
width: '200px',
height: '200px',
zIndex: 1000,
position: 'absolute',
top: '50%',
left: '50%',
},
// any other theme overwrites here
'button.default': {
borderRadius: '32px',
},
'chatbubble.question': {
background: '#F1F5FA',
},
});
// Add customTheme in a theme scope
addTheme(customTheme.name, customTheme);
//Set customTheme as an active, optional on demand to apply as an active
setTheme(customTheme.name);
}, []);
}App.tsx: renders aSelectto demonstrate the change
import React from 'react';
import { FlexContainer, Typography, Row, Select, type Option } from 'gd-design-library';
import useCustomTheme from './useCustomTheme';
const items: Option[] = [
{ name: 'Option 1', value: 'option1' },
{ name: 'Option 2', value: 'option2' },
{ name: 'Option 3', value: 'option3' },
];
export default function App() {
useCustomTheme();
return (
<FlexContainer>
<Typography>Custom Themed Select</Typography>
<Row>
<Select items={items} />
</Row>
</FlexContainer>
);
}🤖 AI Integration
GridKit ships a built-in AI integration layer at ./ai that lets LLMs generate UI — either as React/TSX code or as A2UI JSON specs rendered at runtime.
./ai/
├── README.md # AI integration overview
├── PROMPT_USAGE_MANUAL.md # Full prompt usage guide
├── index.d.ts # Main exports (code mode + A2UI mode)
├── prompts.d.ts # buildClaudeSystemPrompt, buildGPT4Prompt, buildGeminiPrompt
├── discovery.d.ts # Component discovery utilities
├── validation.d.ts # Schema & generated-code validation
├── a2ui/ # A2UI JSON spec mode
│ ├── A2UI_PROTOCOL.md # Protocol specification
│ ├── index.d.ts # A2UI exports
│ ├── component-map.d.ts # A2UI type → GridKit component mapping
│ ├── system-prompt.d.ts # buildA2UISystemPrompt(), buildA2UIGeminiRequest()
│ ├── spec-schema.d.ts # A2UISpec TypeScript types
│ └── ui-specification-schema.json # AJV/Gemini responseSchema
└── schemas/ # Component AI schemas (52 components)
├── index.d.ts
├── components.d.ts
├── components/ # Per-component schemas
└── hooks/
└── useTheme.d.tsSee ./ai/README.md for full documentation.
🔄 A2UI Mode — LLM → JSON → UI
A2UI (Agent-to-UI) is a JSON protocol where an LLM produces a structured spec and GridKit renders it at runtime — no JSX required on the consuming side.
Two functions, one shared contract
| Function | Role |
| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| buildA2UISystemPrompt(options?) | Generates the LLM system instruction from the live component map. Injects your actions as the only available action types. |
| renderA2UISpec(spec, actions?) | Takes a validated A2UISpec and renders it as React components. Wires action handler callbacks from the same actions array. |
Pass the same A2UIActionDefinition[] array to both — it is the single source of truth for what actions the LLM can emit and what your app will handle.
buildA2UISystemPrompt
import { buildA2UISystemPrompt } from 'gd-design-library/ai';
const systemInstruction = buildA2UISystemPrompt({
agentId: 'shop-agent',
agentName: 'Shop Assistant',
context: 'E-commerce product catalog assistant for MyShop.',
imageSources: ['cdn.myshop.com'],
locale: 'en-US',
actions: [
{
type: 'add-to-cart',
description: 'Add a product to the cart. payload: { productId: string, quantity: number }',
handler: ({ payload }) => addToCart(payload),
},
{
type: 'open-checkout',
description: 'Navigate to the checkout flow. No payload required.',
handler: () => navigate('/checkout'),
},
],
});Key options:
| Option | Description |
| ----------------------- | -------------------------------------------------------------------------------- |
| agentId / agentName | Identifiers placed in every generated spec's metadata |
| context | Free-form use-case description injected near the top of the prompt |
| actions | App-defined action types — the only way to make actions available to the LLM |
| imageSources | Restrict image src hosts; pass [] to disable remote images entirely |
| locale | BCP 47 locale code; auto-selects EU/US price formatting |
| priceFormat | 'us' · 'eu' · or a PriceFormatCustom object for full control |
| customGuardrails | Extra guardrail rules appended after the system-defined ones |
| customRules | Extra generation rules appended after the system-defined ones |
| theme | 'light' (default) · 'dark' · 'auto' |
renderA2UISpec
import { renderA2UISpec } from 'gd-design-library';
import type { A2UIActionDefinition } from 'gd-design-library/ai';
const actions: A2UIActionDefinition[] = [
{
type: 'add-to-cart',
description: 'Add a product to the cart.',
handler: ({ payload }) => addToCart(payload),
},
];
function AgentResponse({ spec }) {
return <>{renderA2UISpec(spec, actions)}</>;
}renderA2UISpec maps every A2UIComponent in the spec to the corresponding GridKit component, resolves layout (vertical / horizontal / grid), and dispatches action callbacks when user events fire. Returns null for empty or invalid specs.
Schema validation — ui-specification-schema.json
Every A2UI response should be validated before rendering. The schema is exported from the package:
import schema from 'gd-design-library/ai/ui-specification-schema.json';
import Ajv from 'ajv';
const ajv = new Ajv();
const validate = ajv.compile(schema);
if (!validate(spec)) {
console.error('Invalid A2UI spec:', validate.errors);
}For Gemini structured output, pass A2UI_SPEC_SCHEMA directly as responseSchema to enforce JSON shape at the model level:
import { buildA2UIGeminiRequest, A2UI_SPEC_SCHEMA } from 'gd-design-library/ai';
const model = genAI.getGenerativeModel({
model: 'gemini-2.5-flash',
generationConfig: {
responseMimeType: 'application/json',
responseSchema: A2UI_SPEC_SCHEMA,
},
});
const result = await model.generateContent(
buildA2UIGeminiRequest('Show a product analytics dashboard', {
agentId: 'analytics-agent',
context: 'Product analytics for an e-commerce platform.',
})
);The schema enforces the full A2UISpec structure including version, metadata, ui.layout, ui.components, and ui.actions. The agent service retries up to 3 times on validation failure.
📘 Documentation
Explore our hosted Storybook:
👉 https://storybook.cto-rnd-system-design.griddynamics.net
📄 License
© Grid Dynamics. All rights reserved.
This package is for internal and authorized client use only.
