Skip to content

Setting Up STUDS with Turborepo

A modern, tree-shakeable React component library built with Turborepo.

Creating a New Project

Create a new STUDS project using the design system template:

bash
# Create new project
npx create-turbo@latest -e design-system

# Install dependencies
pnpm install

Project Structure

.
├── apps/
│   └── docs/                 # Storybook documentation
├── packages/
│   ├── ui/                   # Core components
│   ├── eslint-config/       # Shared ESLint config
│   └── typescript-config/   # Shared TS config
├── package.json
└── turbo.json

Key Features

  • 🌳 Tree-shaking support
  • 📚 Storybook documentation
  • 🏗️ TypeScript
  • 📦 Automated publishing
  • 🔄 Versioning with Changesets
  • ⚡ Fast builds with Turborepo

Development Workflow

bash
# Start development environment
pnpm dev         # Runs Storybook + watch mode

# Build packages
pnpm build       # Builds all packages

# Lint code
pnpm lint        # Runs ESLint

# Clean builds
pnpm clean       # Removes build artifacts

Commands Reference

bash
# Development
pnpm dev              # Start Storybook
pnpm build            # Build all packages
pnpm lint             # Lint code
pnpm clean            # Clean builds

# Versioning
pnpm changeset        # Create changeset
pnpm version          # Update versions
pnpm publish          # Publish packages

# Storybook
pnpm storybook        # Start Storybook
pnpm build-storybook  # Build static site

Package Structure

Each component is individually exported:

typescript
// packages/ui/src/button.tsx
export interface ButtonProps {
  children: React.ReactNode;
}

export function Button(props: ButtonProps) {
  return <button>{props.children}</button>;
}

Tree-Shaking

Enabled by default with:

json
// ui/package.json
{
  "sideEffects": false,
  "exports": {
    "./button": {
      "types": "./src/button.tsx",
      "import": "./dist/button.mjs",
      "require": "./dist/button.js"
    }
  }
}

Build Output

After building:

packages/ui/dist/
├── button.d.mts    # ESM types
├── button.d.ts     # CJS types
├── button.js       # CJS bundle
└── button.mjs      # ESM bundle

Usage

typescript
// ESM
import { Button } from '@studs/ui/button';

// CommonJS
const { Button } = require('@studs/ui/button');

Storybook

Located in apps/docs:

typescript
// apps/docs/stories/button.stories.tsx
import { Button } from '@studs/ui/button';

export default {
  title: 'Components/Button',
  component: Button,
};

export const Default = () => <Button>Click me</Button>;

Versioning & Publishing

  1. Create changeset:
bash
pnpm changeset
  1. Update versions:
bash
pnpm changeset version
  1. Publish:
bash
pnpm changeset publish

CI/CD Setup

  1. Add secrets to GitHub:

    • NPM_TOKEN
    • GITHUB_TOKEN
  2. Automated publishing workflow:

yaml
name: Release
on:
  push:
    branches:
      - main
jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: changesets/action@v1

Configuration Files

json
// turbo.json
{
  "pipeline": {
    "build": {
      "outputs": ["dist/**"]
    },
    "dev": {
      "cache": false
    }
  }
}
json
// packages/ui/package.json
{
  "name": "@studs/ui",
  "sideEffects": false,
  "publishConfig": {
    "access": "public"
  }
}

Sources: