Complete monorepo structure with all packages and their relationships.
@mining-sdk/ui-dev-kit/
βββ packages/
β βββ core/ # Core UI components, utilities, types, and theme system
β βββ foundation/ # All-in-one foundation package (domain, feature, hooks, api, state, test-utils)
β βββ fonts/ # Font assets (JetBrains Mono)
βββ apps/
β βββ demo/ # Interactive demo application
β βββ cli/ # CLI tools (placeholder)
βββ docs/ # Documentation files
β βββ ARCHITECTURE.md
β βββ BUILD_SCRIPTS.md
β βββ BUILD_SYSTEM.md
β βββ CONTRIBUTING.md
β βββ SCSS_SETUP.md
β βββ STRUCTURE.md
β βββ WATCH_MODE_GUIDE.md
βββ scripts/ # Build and utility scripts
Purpose: Core UI components, utilities, types, and theme system built on Radix UI primitives
Location: packages/core
Exports:
- Core types (Status, Pagination, ApiResponse, ComponentProps, etc.)
- Utility functions (cn, formatNumber, formatDate, validation)
- Radix UI-based components (Button, Dialog, Switch, Accordion, Alert Dialog, Avatar, Checkbox, etc.)
- Chart components (Chart.js, Lightweight Charts integration)
- Table components (TanStack Table integration)
- Form components with React Hook Form integration
- Theme utilities and CSS variables
Key Dependencies:
- Radix UI primitives (@radix-ui/react-*)
- TanStack Table (@tanstack/react-table)
- Chart.js (chart.js, react-chartjs-2, chartjs-plugin-*)
- Lightweight Charts
- Class Variance Authority (cva)
- clsx, date-fns
Exports Structure:
.β Built JavaScript (dist/index.js) with types (dist/index.d.ts)./styles.cssβ Compiled CSS (dist/styles.css)./stylesβ SCSS mixins for consumers (src/styles/_mixins.scss)
Note: Core exports built files (requires pnpm build before use)
Usage:
import { Button, Dialog, cn, formatDate } from '@mining-sdk/core'
import '@mining-sdk/core/styles.css'Purpose: All-in-one foundation package containing domain components, features, hooks, API client, state management, and test utilities
Location: packages/foundation
Internal Structure:
src/components/domain/- Mining-specific business componentssrc/components/feature/- Complete feature compositionssrc/hooks/- Custom React hookssrc/api/- API client integrationsrc/state/- Redux state managementsrc/test-utils/- Testing utilitiessrc/constants/- Shared constantssrc/utils/- Utility functionssrc/types/- TypeScript type definitions
Exports Structure:
.β Main exports (TypeScript source: src/index.ts)./domainβ Domain-specific components (src/components/domain/index.ts)./featureβ Feature compositions (src/components/feature/index.ts)./hooksβ Custom React hooks (src/hooks/index.ts)./apiβ API client and queries (src/api/index.ts)./stateβ Redux store and slices (src/state/index.ts)./test-utilsβ Testing helpers (src/test-utils/index.ts)./styles.cssβ Compiled CSS (dist/styles.css)
Note: Foundation exports TypeScript source files directly (no build step needed for workspace dependencies)
Key Dependencies:
@mining-sdk/core(workspace)- Redux Toolkit (@reduxjs/toolkit)
- React Redux (react-redux)
- Testing Library (@testing-library/react)
- Vitest
- Lodash, date-fns
Usage Examples:
// Main exports
import { SomeComponent } from '@mining-sdk/foundation'
// Domain components
import { MinerCard, PoolStats } from '@mining-sdk/foundation/domain'
// Feature compositions
import { Dashboard } from '@mining-sdk/foundation/feature'
// Hooks
import { useLocalStorage, useDebounce } from '@mining-sdk/foundation/hooks'
// API client
import { useGetMinersQuery } from '@mining-sdk/foundation/api'
// State management
import { store, useAppSelector } from '@mining-sdk/foundation/state'
// Testing utilities
import { render, mockMiner } from '@mining-sdk/foundation/test-utils'
// Styles
import '@mining-sdk/foundation/styles.css'Purpose: Font assets for the Mining SDK UI Kit
Location: packages/fonts
Exports:
- JetBrains Mono font files and CSS
Exports Structure:
./jetbrains-mono.cssβ Font face definitions and files
Usage:
import '@mining-sdk/fonts/jetbrains-mono.css'ββββββββββββββββββββββββββββββββββββββββββββββββ
β @mining-sdk/core β
β β’ Components (Radix UI-based) β
β β’ Types & Utilities β
β β’ Theme & Styles β
β β’ Charts & Tables β
ββββββββββββββββββ¬ββββββββββββββββββββββββββββββ
β
β workspace:*
β
ββββββββββββββββββΌββββββββββββββββββββββββββββββ
β @mining-sdk/foundation β
β β’ Domain Components (./domain) β
β β’ Feature Compositions (./feature) β
β β’ Custom Hooks (./hooks) β
β β’ API Client (./api) β
β β’ State Management (./state) β
β β’ Test Utilities (./test-utils) β
ββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββ
β @mining-sdk/fonts β
β β’ JetBrains Mono font assets β
ββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββ
β Apps β
β β
β @mining-sdk/demo β
β ββ depends on: @mining-sdk/core β
β ββ depends on: @mining-sdk/foundation β
β ββ depends on: @mining-sdk/fonts β
ββββββββββββββββββββββββββββββββββββββββββββββββ
Key Points:
- Simple two-layer architecture:
coreβfoundation - Foundation package uses internal folder structure but exports via multiple entry points
- All packages use TypeScript source exports (no build step for workspace dependencies)
- Demo app consumes all three packages
- Node.js: >= 20.0.0
- pnpm: >= 10.0.0
# Enable pnpm via corepack (if not already enabled)
corepack enable
# Install all workspace packages
pnpm install# Run only the demo app in dev mode
pnpm dev:demo# Run all packages in watch mode
pnpm dev
# Or run packages only (excluding demo)
pnpm dev:packages# Build all packages
pnpm build
# Build with verbose output
pnpm build:verbose
# Build only demo
pnpm build:demo
# Build only SCSS
pnpm build:scss
# Build only TypeScript
pnpm build:ts# Type checking
pnpm typecheck
# Linting
pnpm lint
pnpm lint:fix
# Code formatting
pnpm format
# Run all checks (lint + typecheck + format + build)
pnpm fullcheck
# Run tests
pnpm test
pnpm test:watch# Analyze bundle sizes
pnpm size# Watch all packages
pnpm watch
# Watch SCSS only
pnpm watch:scss
# Watch TypeScript only
pnpm watch:ts# Build and preview the demo app
pnpm build:demo
pnpm preview:demoThe project uses Turborepo for orchestrating builds and tasks across the monorepo:
Key Features:
- Intelligent caching - Skips tasks that haven't changed
- Parallel execution - Runs independent tasks concurrently
- Task dependencies - Ensures build order is correct
- Remote caching - Share cache across team (optional)
Configuration: turbo.json
Task Pipeline:
{
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"dev": {
"cache": false,
"persistent": true
}
}Configuration: pnpm-workspace.yaml
Workspace structure:
packages:
- 'apps/*'
- 'packages/*'Filter Commands:
# Run command in specific package
pnpm --filter @mining-sdk/core build
# Run command in all packages
pnpm -r build
# Run command in package and its dependencies
pnpm --filter @mining-sdk/demo... buildThe project uses a consolidated package structure. Instead of creating new packages, add features to existing ones:
For new core components, utilities, or types:
# Create component directory
mkdir -p packages/core/src/components/my-component
# Create component files
touch packages/core/src/components/my-component/index.tsx
touch packages/core/src/components/my-component/styles.scssThen export from packages/core/src/index.ts:
export * from './components/my-component'Foundation uses export paths for organization:
-
Domain components β
src/components/domain/- Export via
./domainpath
- Export via
-
Feature compositions β
src/components/feature/- Export via
./featurepath
- Export via
-
Hooks β
src/hooks/- Export via
./hookspath
- Export via
-
API β
src/api/- Export via
./apipath
- Export via
-
State β
src/state/- Export via
./statepath
- Export via
Example: Adding a new domain component
# Create component
mkdir -p packages/foundation/src/components/domain/my-component
touch packages/foundation/src/components/domain/my-component/index.tsxExport in packages/foundation/src/components/domain/index.ts:
export * from './my-component'Only create new packages for major new concerns (e.g., new rendering engine, completely separate design system):
- Create package structure:
mkdir -p packages/my-package/src- Create
package.jsonfollowing the existing pattern:
{
"name": "@mining-sdk/my-package",
"version": "0.0.0",
"private": true,
"type": "module",
"exports": {
".": {
"types": "./src/index.ts",
"default": "./src/index.ts"
}
},
"scripts": {
"build": "tsc",
"typecheck": "tsc --noEmit",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"clean": "rimraf dist node_modules .turbo"
},
"dependencies": {
"@mining-sdk/core": "workspace:*"
}
}- Create
tsconfig.json:
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src",
"composite": true,
"declarationDir": "./dist"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}- Create
src/index.ts:
export * from './my-feature'- Install dependencies:
pnpm install- Always use
workspace:*for internal package dependencies - Use peer dependencies for React, Redux, and other shared libraries
- Keep dependencies minimal - only add what's truly needed
- Use
catalog:for shared dependency versions (defined in pnpm-workspace.yaml)
The project uses pnpm's catalog feature to manage shared dependency versions across all packages:
# pnpm-workspace.yaml
catalog:
react: ^18.3.1
'@radix-ui/react-dialog': ^1.1.4
# ... more shared versionsIn package.json files, reference catalog versions:
{
"dependencies": {
"react": "catalog:",
"@radix-ui/react-dialog": "catalog:"
}
}Benefits:
- Single source of truth for dependency versions
- Easier to update versions across all packages
- Prevents version conflicts in the monorepo
- TypeScript source exports - Packages export
.tsfiles directly for fast dev iteration - Multiple entry points - Use subpath exports for logical grouping (e.g.,
./domain,./hooks) - Use named exports - Avoid default exports for better tree-shaking
- Single index per module - Each feature/component has one
index.ts
- Consolidate related code - Keep related features in the same package
- Use folder structure for organization - Leverage internal folders and export paths
- Only create new packages for major concerns - Avoid package proliferation
- Extend base config - All packages use
tsconfig.base.json - Enable strict mode - Catch errors early with strict type checking
- Export all types - Make types available to consumers
- Use composite projects - Enable faster builds with project references
- SCSS for source - Write styles in SCSS, build to CSS
- CSS modules or BEM - Scope styles to avoid conflicts
- Export compiled CSS - Packages expose
./styles.css - Shared mixins - Core exports SCSS mixins via
./stylespath
- Use foundation test-utils - Import from
@mining-sdk/foundation/test-utils - Test in isolation - Mock external dependencies
- Vitest for unit tests - Fast, ESM-native testing
- React Testing Library - Test components like users interact with them
The project uses a two-layer architecture instead of many micro-packages:
-
Core Layer (
@mining-sdk/core)- Radix UI-based components
- Type definitions and utilities
- Theme and styling system
- Chart and table integrations
-
Foundation Layer (
@mining-sdk/foundation)- Domain-specific components
- Feature compositions
- State management
- API client
- Hooks and utilities
Why this approach?
- Simpler dependency management - No complex dependency trees
- Faster development - Less package overhead, clearer structure
- Better DX - Single import path per concern, not per component
- Easier refactoring - Move code between folders, not packages
- Type safety - No circular dependency issues
Instead of creating separate packages, we use subpath exports:
{
"exports": {
".": "./src/index.ts",
"./domain": "./src/components/domain/index.ts",
"./hooks": "./src/hooks/index.ts"
}
}Benefits:
- Logical code organization
- Tree-shakeable imports
- Clear API boundaries
- No package.json overhead
The project uses a mixed approach for package exports:
{
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
}
}Why built files for Core?
- Heavy dependencies (Radix UI, Chart.js, TanStack Table)
- Complex TypeScript transformations
- Needs optimizations (minification, tree-shaking)
- More stable API surface
{
"exports": {
".": {
"types": "./src/index.ts",
"default": "./src/index.ts"
}
}
}Why source files for Foundation?
- Instant feedback - No build step needed for workspace dependencies
- Faster iteration - Changes reflected immediately in demo app
- Better debugging - Original source in stack traces
- Simpler workflow - Less build orchestration needed
Trade-off:
- Foundation consumers must be able to compile TypeScript
- Not suitable for publishing to npm without pre-build step
Source β Build β Consume:
- Write in SCSS -
src/styles/*.scss - Build to CSS -
dist/styles.css(via Vite) - Export CSS -
./styles.cssexport path - Consume in apps -
import '@mining-sdk/core/styles.css'
Why separate CSS?
- Control over when styles are loaded
- Easier to customize or override
- Better for CSS-in-JS migration path
- Clear separation of concerns
- README - Project overview and quick start
- ARCHITECTURE - System architecture and design decisions
- BUILD_SYSTEM - Build system and tooling
- BUILD_SCRIPTS - Build scripts documentation
- SCSS_SETUP - SCSS/styling setup and guidelines
- WATCH_MODE_GUIDE - Development watch mode guide
- CONTRIBUTING - How to contribute to the project
# Clean all packages and turbo cache
pnpm clean
# Clean just turbo cache
rm -rf .turbo
# Reinstall dependencies from scratch
pnpm clean
rm -rf pnpm-lock.yaml
pnpm install
# Rebuild everything
pnpm build
# Rebuild with verbose output to see errors
pnpm build:verbose# Type check all packages
pnpm typecheck
# Type check specific package
pnpm --filter @mining-sdk/core typecheck
# Clean TypeScript build info
find . -name "tsconfig.tsbuildinfo" -delete
pnpm typecheck# Auto-fix all packages
pnpm lint:fix
# Lint specific package
pnpm --filter @mining-sdk/core lint
pnpm --filter @mining-sdk/core lint:fix
# Format code
pnpm format# Rebuild SCSS only
pnpm build:scss
# Watch SCSS for changes
pnpm watch:scss
# Check for SCSS syntax errors
pnpm --filter @mining-sdk/core build:scss# Kill any processes on port 5173 (Vite default)
lsof -ti:5173 | xargs kill -9
# Restart dev server
pnpm dev:demo
# Clear Vite cache
rm -rf apps/demo/node_modules/.vite
pnpm dev:demo# Verify workspace dependencies are linked
pnpm ls -r
# Check for phantom dependencies
pnpm audit
# Update all catalog dependencies
# Edit pnpm-workspace.yaml, then:
pnpm install
# Dedupe dependencies
pnpm dedupe# Clear all caches
rm -rf .turbo
rm -rf **/node_modules/.vite
rm -rf **/node_modules/.cache
rm -rf **/dist
# Rebuild from scratch
pnpm install
pnpm buildIssue: "Cannot find module '@mining-sdk/core'"
- Ensure packages are built:
pnpm build - Check workspace is properly linked:
pnpm install
Issue: "Styles not updating"
- SCSS needs to be rebuilt:
pnpm build:scssorpnpm watch:scss - Clear Vite cache:
rm -rf apps/demo/node_modules/.vite
Issue: "Type errors in IDE but not in CLI"
- Restart TypeScript server in your IDE
- Delete
tsconfig.tsbuildinfofiles:find . -name "*.tsbuildinfo" -delete
Issue: "Changes not reflected in demo app"
- Ensure watch mode is running:
pnpm devorpnpm watch - Check that source exports are configured (not built dist/)