Add a Shared Package to Your Makerkit Monorepo

Create reusable packages for shared business logic, utilities, or components across your Turborepo monorepo applications.

Create shared packages in your Makerkit monorepo using turbo gen to scaffold a new package at packages/@kit/<name>. Shared packages let you reuse business logic, utilities, or components across multiple applications while maintaining a single source of truth.

Create a Shared Package

Add a new package to your monorepo

When to Create a Package

Create a shared package when:

  • Multiple applications: Code needs to be used across apps/web and other applications
  • Clear boundaries: You want to enforce separation between different domains
  • Reusable utilities: Generic utilities that could be used in any application
  • Shared types: TypeScript types shared across the codebase

Keep code in apps/web when:

  • It's only used in one application
  • It's tightly coupled to specific routes or pages
  • Creating a package adds complexity without benefit

Step 1: Generate the Package

Use the Turborepo generator to scaffold a new package:

turbo gen

Follow the prompts:

  1. Select "Create a new package"
  2. Enter the package name (e.g., analytics)
  3. Optionally add dependencies

The generator creates a package at packages/@kit/analytics with this structure:

packages/@kit/analytics/
├── src/
│ └── index.ts
├── package.json
└── tsconfig.json

Package.json Structure

packages/@kit/analytics/package.json

{
"name": "@kit/analytics",
"version": "0.0.1",
"main": "./src/index.ts",
"types": "./src/index.ts",
"exports": {
".": "./src/index.ts"
},
"scripts": {
"typecheck": "tsc --noEmit"
},
"devDependencies": {
"typescript": "^5.9.0"
}
}

Step 2: Configure Exports

Single Export (Simple)

For packages with a single entry point, export everything from index.ts:

packages/@kit/analytics/src/index.ts

export { trackEvent, trackPageView } from './tracking';
export { AnalyticsProvider } from './provider';
export type { AnalyticsEvent, AnalyticsConfig } from './types';

Import in your application:

import { trackEvent, AnalyticsProvider } from '@kit/analytics';

Multiple Exports (Tree-Shaking)

For packages with client and server code, use multiple exports for better tree-shaking:

packages/@kit/analytics/package.json

{
"name": "@kit/analytics",
"exports": {
".": "./src/index.ts",
"./client": "./src/client.ts",
"./server": "./src/server.ts"
}
}

Create separate entry points:

packages/@kit/analytics/src/client.ts

// Client-side analytics (runs in browser)
export { useAnalytics } from './hooks/use-analytics';
export { AnalyticsProvider } from './components/provider';

packages/@kit/analytics/src/server.ts

// Server-side analytics (runs on server only)
export { trackServerEvent } from './server/tracking';
export { getAnalyticsClient } from './server/client';

Import the specific export:

// In a Client Component
import { useAnalytics } from '@kit/analytics/client';
// In a Server Component or Server Action
import { trackServerEvent } from '@kit/analytics/server';

When to Use Multiple Exports

Use multiple exports when:

  • Client/server separation: Code that should only run in one environment
  • Large packages: Reduce bundle size by allowing apps to import only what they need
  • Optional features: Features that not all consumers need

Step 3: Add to Next.js Config

For hot module replacement (HMR) to work during development, add your package to the INTERNAL_PACKAGES array in apps/web/next.config.mjs:

apps/web/next.config.mjs

const INTERNAL_PACKAGES = [
'@kit/ui',
'@kit/auth',
'@kit/supabase',
// ... existing packages
'@kit/analytics', // Add your new package
];

This tells Next.js to:

  1. Transpile the package (since it's TypeScript)
  2. Watch for changes and trigger HMR
  3. Include it in the build optimization

Step 4: Use the Package

Add as Dependency

Add the package to your application's dependencies:

apps/web/package.json

{
"dependencies": {
"@kit/analytics": "workspace:*"
}
}

Run pnpm install to link the workspace package.

Import and Use

apps/web/app/layout.tsx

import { AnalyticsProvider } from '@kit/analytics';
export default function RootLayout({ children }) {
return (
<html>
<body>
<AnalyticsProvider>
{children}
</AnalyticsProvider>
</body>
</html>
);
}

apps/web/app/home/page.tsx

import { trackPageView } from '@kit/analytics';
export default function HomePage() {
trackPageView({ page: 'home' });
return <div>Welcome</div>;
}

Package Development Patterns

Adding Dependencies

Add dependencies to your package:

pnpm --filter @kit/analytics add zod

Using Other Workspace Packages

Reference other workspace packages:

packages/@kit/analytics/package.json

{
"dependencies": {
"@kit/shared": "workspace:*"
}
}

TypeScript Configuration

The package's tsconfig.json should extend the root configuration:

packages/@kit/analytics/tsconfig.json

{
"extends": "../../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"]
}

Testing Packages

Add tests alongside your package code:

packages/@kit/analytics/
├── src/
│ ├── index.ts
│ └── tracking.ts
└── tests/
└── tracking.test.ts

Run tests:

pnpm --filter @kit/analytics test

Example: Creating a Feature Package

Here's a complete example of creating a notifications package:

1. Generate

turbo gen
# Name: notifications

2. Structure

packages/@kit/notifications/
├── src/
│ ├── index.ts
│ ├── client.ts
│ ├── server.ts
│ ├── components/
│ │ └── notification-bell.tsx
│ ├── hooks/
│ │ └── use-notifications.ts
│ └── server/
│ └── send-notification.ts
└── package.json

3. Exports

packages/@kit/notifications/package.json

{
"name": "@kit/notifications",
"exports": {
".": "./src/index.ts",
"./client": "./src/client.ts",
"./server": "./src/server.ts"
},
"dependencies": {
"@kit/supabase": "workspace:*"
}
}

4. Implementation

packages/@kit/notifications/src/client.ts

export { NotificationBell } from './components/notification-bell';
export { useNotifications } from './hooks/use-notifications';

packages/@kit/notifications/src/server.ts

export { sendNotification } from './server/send-notification';

5. Use

// Client Component
import { NotificationBell } from '@kit/notifications/client';
// Server Action
import { sendNotification } from '@kit/notifications/server';

Troubleshooting

Module not found

  1. Ensure the package is in INTERNAL_PACKAGES in next.config.mjs
  2. Run pnpm install to link workspace packages
  3. Check the export path matches your import

Types not resolving

Ensure tsconfig.json includes the package paths:

{
"compilerOptions": {
"paths": {
"@kit/*": ["./packages/@kit/*/src"]
}
}
}

HMR not working

Verify the package is listed in INTERNAL_PACKAGES and restart the dev server.