Canonical reference for the spring-design-library monorepo: what every folder is, why it exists, and how the pieces connect.
1. Purpose & Quick Start
This repository is the Spring Design System for the Opportunity Generation team at Spring Financial. It contains:
@spring/ds-react— React components, design tokens, and Figma-synced icons (the product UI source of truth).@spring/design-library— A Next.js documentation gallery at/library/*(replaces Storybook).
Commands (from repo root)
| Command | Purpose |
|---|---|
npm install | Install all workspace dependencies |
npm run dev | Start the design library (Next.js dev server) |
npm run build | Production build of the design library and personal-loan app |
npm run preview | Serve built app on port 5180 (manual QA) |
npm run dev:personal-loan | Start the standalone personal-loan app |
npm run build:personal-loan | Production build of the standalone personal-loan app |
npm run preview:personal-loan | Serve the standalone personal-loan app on port 5181 |
npm run tokens:sync | Regenerate CSS variables from design-tokens.mjs |
npm run tokens:figma | Pull Figma Variables into figma-variables.json |
npm run icons:sync | Sync icon components from Figma |
npm run code-connect:parse | Validate Figma Code Connect mappings |
npm run code-connect:publish | Publish Code Connect to Figma |
npm run lint | ESLint across app, package, scripts, and manual-qa |
Environment
Copy .env.example to .env for Figma sync:
FIGMA_TOKEN— Figma personal access tokenFIGMA_FILE_ID— Foundation file ID for token pull
2. Architecture Overview
flowchart TB
subgraph monorepo [Active Monorepo]
root["Root npm workspace\nspring-design-library"]
app["apps/design-library\nNext.js gallery"]
pkg["packages/spring-ds-react\nComponents + tokens + icons"]
scripts["scripts/"]
figma["figma.config.json"]
end
root --> app
root --> pkg
root --> scripts
root --> manual-qa
figma --> app
figma --> pkg
scripts --> pkg
app --> pkg
manual-qa --> app
Scale: ~1,350 files total; ~1,173 are auto-generated icon components under packages/spring-ds-react/src/icons/.
Workspaces: npm workspaces (apps/*, packages/*). No Turborepo or pnpm.
3. Top-Level Map
| Path | Purpose | Status |
|---|---|---|
apps/ | Workspace applications | Active |
packages/ | Workspace packages (design system) | Active |
scripts/ | Root tooling (token sync, manual QA preview) | Active |
docs/ | Documentation hub — start at docs/README.md | Active |
.cursor/rules/ | Short executable Cursor rules derived from docs/ai/ | Active |
.cursor/skills/ | Project skills for repeatable agent workflows | Active |
figma.config.json | Figma Code Connect parser config | Active |
tsconfig.json | Shared TypeScript paths | Active |
.env.example | Figma API env template | Active |
.github/workflows/ | CI pipeline | Active |
README.md | Team onboarding + docs links | Active |
4. apps/design-library — Documentation Gallery
Package: @spring/design-library
Stack: Next.js 16 (App Router), React 19, TypeScript, Tailwind CSS
URL base: /library/*
Architecture Pattern
The app uses thin route shells + gallery implementations:
src/app/library/**/page.tsx— Next.js routes (filesystem routing)src/gallery/**— Doc UI, navigation, component pages, AppFlow previews
Most routes are one-liners that re-export a gallery page:
import TextFieldPage from '@/gallery/pages/components/inputs/TextFieldPage'
export default TextFieldPage
Directory Tree
apps/design-library/
├── next.config.ts # transpilePackages + @spring/ds-react aliases
├── postcss.config.js
├── tailwind.config.mjs # theme from @spring/ds-react/tokens
├── tsconfig.json # excludes *.figma.tsx from typecheck
├── package.json
└── src/
├── app/ # Next.js App Router (~50 page.tsx routes)
│ ├── layout.tsx # root: Inter font, token CSS, globals.css
│ ├── page.tsx # redirect → /library/getting-started
│ ├── not-found.tsx
│ └── library/
│ ├── layout.tsx # LibraryAppLayout wrapper
│ ├── getting-started/
│ ├── design-tokens/ # colors, typography, space, styles, layout (placeholder)
│ ├── icons/
│ ├── components/ # navigations, actions, inputs, overlays, etc.
│ ├── design-libraries/ # reserved (no routes until product libraries ship)
│ └── page/appflow/ # personal loan flow
├── gallery/
│ ├── layout/ # LibraryAppLayout, LibraryShellSidebar
│ ├── navigation/ # libraryNav.ts (sidebar source of truth)
│ ├── components/ # Doc primitives: CodeBlock, TokenRoleSwatch, etc.
│ ├── pages/ # Full doc pages + 7 *.figma.tsx Code Connect files
│ ├── foundations/ # Token foundation pages (typography, spacing, radius)
│ └── page/appflow/ # Personal loan flow (14 screens + registry)
├── lib/ # App-only: tokenDatasets, iconManifest, utils, useHash
├── styles/globals.css
└── middleware.ts # Redirects / and non-/library/* → /library/getting-started
Route Categories
| Section | Live routes | Placeholder routes (hidden from nav) |
|---|---|---|
| Getting Started | 1 | — |
| Design Tokens | 4 (colors, typography, space, styles) | 1 (layout) |
| Icons | 1 | — |
| Components | ~25 doc pages across 6 categories | 12 (section hubs + empty categories) |
| AppFlow | Personal loan flow with dynamic [slug] | — |
| Design Libraries | — | 3 |
Placeholder policy: see PLACEHOLDER_POLICY.md.
Key Integration Points
| File | Role |
|---|---|
src/app/layout.tsx | SSR import of @spring/ds-react/tokens/generated/css-variables.css |
next.config.ts | transpilePackages: ['@spring/ds-react']; source aliases to package |
tailwind.config.mjs | content scans app + package; theme from token exports |
src/gallery/navigation/libraryNav.ts | Sidebar structure — only live pages appear here |
Figma Code Connect (app-side)
7 files under src/gallery/pages/components/**:
- Navigations: SpringHeader, SpringFooter, SpringFooterLegal
- Overlays: ExitModal, InfoModal, ConfirmModal, ActionModal
- Selection: SpringSearchBar
Excluded from TypeScript build (tsconfig.json); parsed by figma.config.json.
5. packages/spring-ds-react — Design System
Package: spring-design-library-react (linked internally as @spring/ds-react)
Role: The single published package — React components, tokens, icons, design-system rules, and the AppFlow/page map.
Directory Tree
packages/spring-ds-react/
├── package.json # exports: ., ./components, ./icons, ./tokens, ./tokens/generated/css-variables.css, ./rules, ./appflow
├── tsconfig.json
├── tsup.config.ts # builds index, icons, rules, appflow; copies tokens to dist
├── scripts/
│ ├── sync-spring-icons-from-figma.mjs
│ └── publish-manifest.mjs
└── src/
├── index.ts # Public API barrel (~20 components) — root + ./components
├── gallery-order.ts # GALLERY_COMPONENT_CATEGORIES
├── tokens/ # SOURCE OF TRUTH — ./tokens
│ ├── design-tokens.mjs # primitives + semantic + figmaMap
│ ├── core.mjs # runtime assembly, getByPath, figmaNameToCssVar
│ ├── index.mjs # spring-design-library-react/tokens export
│ ├── build-utils.mjs
│ └── generated/
│ ├── css-variables.css # 254 CSS variables (committed)
│ └── sync-manifest.json
├── rules/ # Structured design-system rules — ./rules
├── appflow/ # AppFlow/page-map barrel — ./appflow (bundles @spring/personal-loan-appflow)
├── components/
│ ├── inputs/ # 11 components + index.ts + 10 *.figma.tsx
│ ├── navigations/ # SpringHeader, SpringFooter, SpringFooterLegal, SpringLogo
│ ├── actions/ # SpringButton
│ ├── overlays/ # ExitModal, InfoModal, ConfirmModal, ActionModal (modals.tsx)
│ ├── selection-input/# SpringSearchBar
│ ├── feedback/ # SpringProgress
│ └── [reserved]/ # layout-structure, lists, tables, image-icons, utilities (empty)
├── icons/ # 20 Figma categories, ~1,173 .tsx (auto-synced)
├── assets/ # Canonical logos, tile-selector glyphs, bank logos
├── layout/ # Reserved: app-shell, layout-shell (empty)
├── patterns/ # Reserved for composed screens (.gitkeep)
└── design-libraries/ # Reserved for product libraries (empty)
Public Exports
Published as spring-design-library-react; internal imports use the @spring/ds-react link.
| Subpath | Resolves to |
|---|---|
spring-design-library-react / /components | ./src/index.ts — all components |
spring-design-library-react/icons | ./src/icons/index.ts |
spring-design-library-react/tokens | ./src/tokens/index.mjs |
spring-design-library-react/tokens/generated/css-variables.css | generated CSS |
spring-design-library-react/rules | ./src/rules/index.ts |
spring-design-library-react/appflow | ./src/appflow/index.ts (bundled at publish) |
Implemented Components (~20)
| Category | Components |
|---|---|
| navigations | SpringHeader, SpringFooter, SpringFooterLegal, SpringLogo |
| actions | SpringButton |
| selection-input | SpringSearchBar |
| inputs | TextField, DropdownField, PhoneNumberField, SplitPillInput, OtpField, SearchField, BoxSelector, LoanAmountSlider, TileSelector, ConsentBox |
| overlays | ExitModal, InfoModal, ConfirmModal, ActionModal |
| feedback-indicators | SpringProgress |
Token Pipeline
flowchart LR
FigmaAPI["Figma Variables API"]
DTM["design-tokens.mjs"]
Sync["scripts/sync-tokens.js"]
CSS["generated/css-variables.css"]
TW["tailwind.config.mjs"]
App["layout.tsx SSR import"]
FigmaAPI -->|"npm run tokens:figma"| Sync
DTM -->|"npm run tokens:sync"| Sync
Sync --> CSS
CSS --> App
DTM --> TW
- Source:
design-tokens.mjs— primitives, semantics,figmaMap, usage metadata. - Build:
npm run tokens:sync→ Zod validation +generated/css-variables.css. - Optional pull:
npm run tokens:figma→figma-variables.json(gitignored). - Consumption: SSR CSS import, Tailwind theme, gallery token docs.
Figma Code Connect (package-side)
11 files under src/components/inputs/*.figma.tsx:
BoxSelector, ConsentBox, DropdownField, FileUploader, LoanAmountSlider, OtpField, PhoneNumberField, SearchField, SplitPillInput, TextField, TileSelector
Icon Sync
npm run icons:sync runs scripts/sync-spring-icons-from-figma.mjs in the package workspace. Icons are organized into 20 categories (General, Arrows, Charts, Communication, etc.) with barrel exports.
6. Scripts & Tooling
| Script | File | Purpose |
|---|---|---|
tokens:sync | scripts/sync-tokens.js | Build token artifacts + Zod validation |
tokens:figma | same | Pull Figma Variables API |
icons:sync | packages/spring-ds-react/scripts/sync-spring-icons-from-figma.mjs | Sync icons from Figma |
code-connect:* | figma.config.json + Figma CLI | Parse/publish Code Connect |
Figma Code Connect Config
figma.config.json:
- Parser: React, TypeScript
- Includes: app gallery
*.figma.tsx, package component*.figma.tsxand all*.tsx - Paths:
@/*→ design-library src,@spring/ds-react→ package index
7. manual QA Testing
| File | Purpose |
|---|
8. Documentation Index
Full hub with reading order: docs/README.md.
| Document | Location | Audience |
|---|---|---|
| Documentation hub | docs/README.md | Entry point — reading order by role |
| Agentic workflow overview | docs/ai/agentic-workflow-overview.md | Leadership — roles, rules, skills, gates (Google Docs–ready) |
| Repository Structure (this file) | docs/REPOSITORY_STRUCTURE.md | All developers |
| Contributing guide | docs/CONTRIBUTING.md | Contributors |
| Component addition workflow | docs/COMPONENT_ADDITION.md | Component authors |
| Placeholder route policy | docs/PLACEHOLDER_POLICY.md | Gallery maintainers |
| AI project context | docs/ai/project-context.md | AI agents |
| AI operational manifesto | docs/ai/operational-manifesto.md | AI agents / codegen orchestration |
| AI workflow contracts | docs/ai/workflow-contracts.md | AI agents / maintainers |
| AI workflow test plan | docs/ai/workflow-test-plan.md | AI agents / QA |
| AI review checklist | docs/ai/review-checklist.md | AI agents |
| UX strategy | docs/ux/ux-strategy-logic.md | UX / product |
| User insights | docs/ux/user-insights-report.md | UX / product |
| Personal loans flow | docs/ux/personal-loans-flow.md | AppFlow authors |
| Vite → Next migration | docs/history/migration-vite-to-next.md | Historical reference |
| App README | apps/design-library/README.md | App developers |
| Package README | packages/spring-ds-react/README.md | DS authors |
| Cursor rules | .cursor/rules/*.mdc | AI agents (short executable rules derived from docs/ai/) |
| Cursor skills | .cursor/skills/*/SKILL.md | AI agents — spring-agentic-workflow, spring-ux-variant |
9. Data Flows
Component: Figma → Code → Gallery
Figma component
→ Code Connect (*.figma.tsx) OR manual implementation
→ packages/spring-ds-react/src/components/<category>/
→ Export from src/index.ts
→ Gallery page in apps/design-library/src/gallery/pages/
→ Route shell in apps/design-library/src/app/library/
→ Nav entry in libraryNav.ts
See COMPONENT_ADDITION.md for the full checklist.
Token: Design → Runtime
Figma Variables (optional pull)
→ design-tokens.mjs (source of truth)
→ npm run tokens:sync
→ clear apps/design-library/.next before production build validation
→ generated/css-variables.css
→ SSR import in layout.tsx + Tailwind theme
AppFlow: Screen Registry
personalLoanFlow.ts (step registry)
→ screens/*.tsx (14 screen components)
→ [slug]/page.tsx (dynamic route)
→ LivePageEmbedPreview / MiniPagePreview
Agentic Workflow: Outcome → Files → Validation
User request
→ docs/ai/project-context.md (intake + outcome routing)
→ docs/ai/operational-manifesto.md (agent roles + workflow)
→ docs/ai/workflow-contracts.md (file targets + injection points)
→ implementation in package, gallery, AppFlow, tokens, docs or rules
→ docs/ai/workflow-test-plan.md (validation matrix)
→ docs/ai/review-checklist.md (handoff quality gate)
Outcome routing:
| Outcome | Primary files | Required injection |
|---|---|---|
| Reusable component | packages/spring-ds-react/src/components/<category>/ | packages/spring-ds-react/src/index.ts |
| Gallery page | apps/design-library/src/gallery/pages/ | route shell + optional libraryNav.ts |
| AppFlow screen | apps/design-library/src/gallery/page/appflow/screens/ | personalLoanFlow.ts |
| Static library page | apps/design-library/src/gallery/pages/ | route shell + optional libraryNav.ts |
| Token/foundation change | packages/spring-ds-react/src/tokens/ | generated token artifacts via tokens:sync |
| Icon change | packages/spring-ds-react/src/icons/ | icon barrels and gallery manifest if needed |
| Docs/rules | docs/ or .cursor/rules/ | documentation indexes |
Code Connect placement is intentionally explicit: new reusable mappings default package-side, input mappings must live under packages/spring-ds-react/src/components/inputs/, and existing gallery-side mappings remain limited to navigations, overlays, and SpringSearchBar until a migration is planned.
10. Technical Debt Register
| Item | Severity | Status / Notes |
|---|---|---|
| Source-only package consumption | Low | App aliases directly to package src/ — acceptable for internal monorepo |
| Empty component categories (5 dirs) | Low | Reserved with README stubs; implement when Figma components land |
| Placeholder gallery hub routes | Low | Hidden from nav; keep as scaffolds or replace with redirects after maintainer confirmation |
| Component barrel files | Low | Only inputs/index.ts exists; main export is src/index.ts |
| Code Connect split | Medium | Inputs are package-side; navigations, overlays, and SpringSearchBar are legacy gallery-side mappings |
| Category taxonomy drift | Medium | inputs is now canonical; feedback-indicators maps to current package folder feedback/ for SpringProgress |
| Next middleware deprecation warning | Low | Next 16 may deprecate middleware → proxy; monitor upgrade guide |
| No Storybook | Info | Custom Next gallery intentionally replaces Storybook |
| External npm publish | Future | No dist/ build step; add if publishing @spring/ds-react externally |
| Turborepo | Future | Consider if more apps/packages are added |
| Completed Cursor plans | Low | Old .cursor/plans/* snapshots can be archived or deleted after maintainer confirmation |
Cleanup Candidates Requiring Confirmation
Do not remove these automatically during agentic workflows. Confirm with a maintainer first:
| Candidate | Suggested action | Why |
|---|---|---|
Old .cursor/plans/* snapshots | Archive or delete | They describe completed migration/restructure states and may confuse agents |
Old .cursor/rules/*.md files | Replaced by scoped .mdc rules | Cursor project rules use .mdc frontmatter |
| Future workflow split skills | Add only after repeated need | Start with spring-agentic-workflow before splitting AppFlow/component/Code Connect skills |
| Duplicate search documentation pages | Consolidate after route/nav review | SearchFieldPage and SpringSearchBarPage may overlap |
| Placeholder hub routes | Keep hidden, or redirect to first live child | Hidden scaffolds are safe, but direct URL access can confuse users |
| Legacy gallery-side Code Connect files | Migrate package-side in a dedicated pass | Current split is documented; migration should be intentional |
11. Future Considerations
These are documented but not yet implemented:
- Turborepo — Add if the monorepo grows beyond 2 workspaces (parallel build/cache).
- Package build step — Add
tsupor similar if@spring/ds-reactneeds external npm publish. - Empty categories — Implement layout-structure, lists, tables, image-icons, utilities as Figma components become available.
- Multi-framework tokens — Tokens ship framework-agnostic via
spring-design-library-react/tokens; a separate package is only needed if consumers cannot depend on this one.
12. Reorganization Status
Summary of the POC → harmonized monorepo cleanup (see also docs/README.md).
Completed
| Change | Details |
|---|---|
| Documentation hub | All root markdown moved to docs/ with role-based index |
| Master structure doc | This file — single canonical repo reference |
| Next.js migration | Gallery app on App Router; Vite entry removed |
| Legacy file cleanup | Removed vite-env.d.ts, shadcn-vue components.json, duplicate app logos, Untitled snippet |
.gitignore expanded | Ignores .next/, out/, *.tsbuildinfo, .vite/ |
| Root package rename | design-ui-ai-system → spring-design-library |
| Category README stubs | Empty package dirs documented for future Figma targets |
| manual QA test alignment | Tests updated for floating-label TextFields and current getting-started copy |
Pending (maintainer actions)
| Action | Why |
|---|---|
| Decide placeholder hub behavior | Keep hidden scaffolds or redirect hubs to first live child |
| Decide Code Connect migration | Migrate legacy gallery-side mappings package-side or keep split documented |
| Archive completed Cursor plans | Avoid agents treating old plan snapshots as current state |
Removed (do not reintroduce)
- Vite app entry (
main.tsx,App.tsx,index.html) fromapps/design-library - Vue/shadcn-vue config (
components.json) - Duplicate Spring logo SVGs in
apps/design-library/src/assets/
13. Related Links
- docs/README.md — documentation hub and reading order
- COMPONENT_ADDITION.md — Adding a new component end-to-end
- PLACEHOLDER_POLICY.md — Placeholder route conventions
- apps/design-library/README.md — App-specific routing docs
- packages/spring-ds-react/README.md — Figma → code path rules