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.
When to Create a Package
Create a package when you have code that needs to be shared across multiple applications or when you want to enforce clear boundaries between different parts of your codebase. For code used only in apps/web, a folder within the app is simpler.
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/weband 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 genFollow the prompts:
- Select "Create a new package"
- Enter the package name (e.g.,
analytics) - Optionally add dependencies
The generator creates a package at packages/@kit/analytics with this structure:
packages/@kit/analytics/├── src/│ └── index.ts├── package.json└── tsconfig.jsonPackage.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 Componentimport { useAnalytics } from '@kit/analytics/client';// In a Server Component or Server Actionimport { 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:
- Transpile the package (since it's TypeScript)
- Watch for changes and trigger HMR
- 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 zodUsing 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.tsRun tests:
pnpm --filter @kit/analytics testExample: Creating a Feature Package
Here's a complete example of creating a notifications package:
1. Generate
turbo gen# Name: notifications2. Structure
packages/@kit/notifications/├── src/│ ├── index.ts│ ├── client.ts│ ├── server.ts│ ├── components/│ │ └── notification-bell.tsx│ ├── hooks/│ │ └── use-notifications.ts│ └── server/│ └── send-notification.ts└── package.json3. 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 Componentimport { NotificationBell } from '@kit/notifications/client';// Server Actionimport { sendNotification } from '@kit/notifications/server';Troubleshooting
Module not found
- Ensure the package is in
INTERNAL_PACKAGESinnext.config.mjs - Run
pnpm installto link workspace packages - 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.
Related Resources
- Adding Turborepo Apps for creating new applications
- Technical Details for monorepo architecture