npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dbarrett24/tsup-config

v1.0.0

Published

Shared tsup configuration for building component libraries

Readme

@yourname/tsup-config

Shared tsup configuration for building component libraries with automatic workspace dependency resolution and client directive injection.

🎯 What This Solves

When building component libraries in a monorepo, you face these challenges:

  1. Workspace Dependencies: During development you use workspace:*, but published packages need actual version numbers
  2. Client Directives: React client components need 'use client'; at the top of every file
  3. Build Consistency: Every library needs the same build configuration
  4. package.json Management: Published packages need a clean dist/package.json with correct entry points

This package automates all of that.


📦 Installation

pnpm add -D @yourname/tsup-config tsup prettier

🚀 Usage

Basic Setup

In your component library's tsup.config.ts:

import { makeConfig } from '@yourname/tsup-config';

export default makeConfig(
    // Server-safe entries (no 'use client' needed)
    {
        index: 'src/index.ts',
        utils: 'src/utils/index.ts',
    },
    // Client component entries (gets 'use client' prepended)
    {
        button: 'src/components/Button.tsx',
        input: 'src/components/Input.tsx',
    }
);

Advanced Setup with Overrides

import { makeConfig } from '@yourname/tsup-config';

export default makeConfig(
    { index: 'src/index.ts' },
    { button: 'src/components/Button.tsx' },
    {
        // Optional overrides
        format: ['cjs', 'esm'],
        external: ['react', 'react-dom'],
        onSuccess: async () => {
            console.log('Build complete!');
        },
    }
);

⚙️ What It Does

1. Automatic Workspace Dependency Resolution

Your package.json:

{
    "dependencies": {
        "@yourname/theme-system": "workspace:*"
    }
}

Generated dist/package.json:

{
    "dependencies": {
        "@yourname/theme-system": "^1.2.3"
    }
}

2. Client Directive Injection

Your component:

// src/components/Button.tsx
export const Button = ({ children }) => {
    return <button>{children}</button>;
};

Built output:

// dist/button.js
'use client';

export const Button = ({ children }) => {
    return <button>{children}</button>;
};

3. Clean package.json Generation

Automatically creates dist/package.json with only:

  • name
  • version
  • dependencies
  • peerDependencies
  • sideEffects
  • main (entry point)
  • types (type definitions)

4. Consistent Build Configuration

All libraries get:

  • TypeScript declaration files (.d.ts)
  • CommonJS and ESM formats
  • Inline source maps
  • Tree-shaking support
  • External node_modules

📋 API Reference

makeConfig(entries, clientEntries?, optionOverrides?)

Parameters:

  • entries (Record<string, string>) - Server-safe entry points
    • Keys: Output file names
    • Values: Source file paths
  • clientEntries (Record<string, string>, optional) - Client component entry points
    • Same format as entries
    • Gets 'use client' prepended automatically
  • optionOverrides (Partial<Options>, optional) - Additional tsup options
    • Any valid tsup configuration option
    • Overrides default settings

Returns: Options - tsup configuration object

defaultConfigObject

The base configuration applied to all builds:

{
  dts: true,                      // Generate .d.ts files
  format: ['cjs', 'esm'],         // Output CommonJS and ESM
  legacyOutput: true,             // Use legacy output structure
  clean: true,                    // Clean dist before build
  sourcemap: 'inline',            // Inline source maps
  splitting: true,                // Enable code splitting
  skipNodeModulesBundle: true,    // Don't bundle node_modules
}

🏗️ Project Structure Example

basketball-training-ui/
├── src/
│   ├── components/
│   │   ├── Button.tsx         # Client component
│   │   └── Input.tsx          # Client component
│   ├── utils/
│   │   └── helpers.ts         # Server-safe utilities
│   └── index.ts               # Main entry
├── dist/                      # Generated by tsup
│   ├── index.js
│   ├── index.d.ts
│   ├── button.js              # Has 'use client'
│   ├── button.d.ts
│   ├── utils.js
│   ├── utils.d.ts
│   └── package.json           # Auto-generated with resolved deps
├── package.json
└── tsup.config.ts             # Uses makeConfig()

🔧 Configuration Tips

Separating Client and Server Code

export default makeConfig(
    // Server/universal code
    {
        index: 'src/index.ts',
        hooks: 'src/hooks/index.ts',
        utils: 'src/utils/index.ts',
    },
    // Client components only
    {
        button: 'src/components/Button.tsx',
        input: 'src/components/Input.tsx',
        modal: 'src/components/Modal.tsx',
    }
);

External Dependencies

Mark React and other large dependencies as external:

export default makeConfig(
    { index: 'src/index.ts' },
    { button: 'src/components/Button.tsx' },
    {
        external: ['react', 'react-dom', 'jotai', '@tanstack/react-query'],
    }
);

Custom Build Output

export default makeConfig(
    { index: 'src/index.ts' },
    { button: 'src/components/Button.tsx' },
    {
        format: ['esm'], // ESM only
        minify: true, // Minify output
        target: 'es2020', // Target specific ECMAScript version
    }
);

🧪 Verifying the Build

After building, check that:

  1. dist/package.json exists with resolved workspace dependencies
  2. Client components have 'use client' at the top
  3. Type definitions are generated (.d.ts files)
pnpm build

# Check package.json
cat dist/package.json

# Check client directive
head -n 1 dist/button.js
# Should show: 'use client';

# Check types
ls dist/*.d.ts

🤝 Integration with Changesets

When using @changesets/cli, this package ensures published versions are correct:

# 1. Make changes to your library
# 2. Create changeset
pnpm changeset

# 3. Version packages (updates version numbers)
pnpm changeset version

# 4. Build (workspace:* gets resolved to actual versions)
pnpm build

# 5. Publish
pnpm changeset publish

📚 Related Packages


🐛 Troubleshooting

"Cannot find package.json in lockfile"

Cause: Package not listed in pnpm-workspace.yaml

Fix:

# pnpm-workspace.yaml
packages:
    - 'brand-libraries/*'
    - 'shared-configs/*'

"'use client' not being added"

Cause: Component listed in entries instead of clientEntries

Fix:

// ❌ Wrong
export default makeConfig({
    button: 'src/components/Button.tsx', // In entries - no 'use client'
});

// ✅ Correct
export default makeConfig(
    {}, // Server entries
    { button: 'src/components/Button.tsx' } // Client entries - gets 'use client'
);

"Workspace dependencies not resolved"

Cause: Building outside of monorepo or lockfile not present

Fix:

  • Ensure you're building from within the monorepo
  • Run pnpm install to generate/update pnpm-lock.yaml
  • Verify pnpm-workspace.yaml includes your package

📄 License

MIT © Your Name