A production-ready Turborepo monorepo template designed to bootstrap new projects quickly.
- Overview
- Prerequisites
- Quick Start
- Project Structure
- Core Features
- Environment Variables
- Generators
- Available Scripts
- Tooling & Configuration
- Docker Support
- CI/CD
- Git Hooks
- Internationalization
- Technology Stack
- Troubleshooting
- Contributing
- License
This monorepo serves as a boilerplate for quickly bootstrapping new Node.js projects. It provides:
- Code generators for creating new applications and packages
- Example implementations (apps & packages) demonstrating the generator outputs
- Shared configurations for consistent tooling across projects
- Production-ready setup with Docker, testing, linting, and i18n
- Clone this boilerplate using
degit(without git history) - Example apps and packages in
apps/andpackages/are automatically removed by degit - Use the built-in generators to create your own apps and packages
- Start building with a solid, consistent foundation
Note: The
apps/andpackages/directories contain example code generated from templates. They demonstrate what the generators produce and are excluded when bootstrapping a new project via degit (see degit.json).
| Requirement | Version | Notes |
|---|---|---|
| Node.js | >= 24.0.0 | Use nvm to manage versions |
| PNPM | >= 10.0.0 | Required package manager |
| NVM | Latest | Recommended for Node.js version management |
# Clone the boilerplate without git history
pnpm dlx degit https://github.com/guillaumecatel/monorepo-boilerplate my-project
# Navigate to the project
cd my-project
# Use the correct Node.js version
nvm use
# Install dependencies
pnpm i
# Configure environment variables
cp .env.example .env
# Edit .env with your organization details
# Initialize git repository
git init
# Create your first app or package
pnpm genIf you're contributing to the boilerplate itself:
# Clone with git history
git clone https://github.com/guillaumecatel/monorepo-boilerplate
cd boilerplate
# Use the correct Node.js version
nvm use
# Install dependencies
pnpm i
# Start development mode
pnpm devImportant: When developing or testing generators, each example app and package must be named exactly like its template. For example:
- Template
astro-websiteβ App namedastro-website- Template
react-packageβ Package namedreact-packageThis naming convention ensures the
pnpm gen:appsandpnpm gen:packagesscripts work correctly to regenerate examples from templates.
.
βββ apps/ # Application examples (excluded by degit)
β βββ astro-website/ # Astro SSR website example
β βββ storybook-react/ # Storybook component library example
β
βββ packages/ # Package examples (excluded by degit)
β βββ react-package/ # React component library example
β βββ typescript-package/ # TypeScript utilities example
β βββ font-package/ # Font distribution example
β
βββ configs/ # Shared configurations
β βββ tailwind-config/ # Tailwind CSS 4 shared config
β βββ typescript-config/ # TypeScript base configurations
β
βββ turbo/ # Turborepo configuration
β βββ generators/ # Code generators (Plop-based)
β βββ config.ts # Generator definitions
β βββ actions.ts # Custom generator actions
β βββ helpers.ts # Template helpers
β βββ validators.ts # Input validation
β βββ templates/ # Generator templates
β βββ apps/ # App templates
β βββ packages/ # Package templates
β βββ internal/ # Shared base templates
β
βββ translations/ # i18n translation files
β βββ en.json # English translations
β βββ fr.json # French translations
β
βββ .github/ # GitHub configuration
β βββ workflows/ # GitHub Actions workflows
β βββ check-code.yml # CI: lint, test, build
β βββ deploy.yml # CD: Docker image deployment
β
βββ .husky/ # Git hooks configuration
β βββ pre-commit # Pre-commit hook
β
βββ project.inlang/ # Paraglide.js configuration
β βββ settings.json # i18n settings
β
βββ .env.example # Environment variables template
βββ .nvmrc # Node.js version (24)
βββ degit.json # degit configuration (excludes examples)
βββ Dockerfile # Multi-stage Docker build
βββ eslint.config.ts # ESLint flat configuration
βββ knip.ts # Knip configuration (unused deps)
βββ package.json # Root package.json
βββ pnpm-workspace.yaml # PNPM workspace configuration
βββ prettier.config.ts # Prettier configuration
βββ turbo.json # Turborepo task configuration
βββ vitest.config.ts # Vitest configuration
- Parallel task execution across all packages
- Smart caching for faster builds
- Task dependencies properly configured
- Persistent dev mode for all apps
- Efficient disk usage with content-addressable storage
- Strict peer dependencies management
- Workspace protocol for local packages (
workspace:*) - Auto-inject workspace packages enabled
- Shared TypeScript configurations in
configs/typescript-config - Strict mode enabled by default
- Path aliases configured per package
- Type checking as a separate task
The generators use environment variables to customize generated code. Copy the example file and configure it:
cp .env.example .env| Variable | Description | Example |
|---|---|---|
ORGANIZATION_SCOPE_NAME |
NPM scope for packages (without @) | guillaumecatel |
ORGANIZATION_NAME |
Organization display name | Guillaume CATEL |
ORGANIZATION_EMAIL |
Contact email for package.json | contact@guillaumecatel.com |
ORGANIZATION_REPOSITORY_NAME |
Repository name | monorepo |
ORGANIZATION_REPOSITORY_URL |
Full repository URL | https://github.com/electroaudiogram/resona |
These variables are used by generators to:
- Set the
@scopeprefix for package names (e.g.,@myorg/my-package) - Configure
authorfield in generatedpackage.jsonfiles - Set
repositoryURLs in package metadata - Generate consistent naming across all packages
The boilerplate includes powerful Turbo generators (Plop-based) for scaffolding new code.
pnpm gen
# Select "app"
# Choose template: astro-website | storybook-react
# Enter application name| Template | Description |
|---|---|
astro-website |
Astro 5 SSR website with i18n, Tailwind CSS 4, security headers |
storybook-react |
Storybook 10 with React 19, accessibility testing, i18n stories |
pnpm gen
# Select "package"
# Choose template: react-package | typescript-package | font-package
# Enter package name| Template | Description |
|---|---|
react-package |
React 19 component library with Vitest + Testing Library |
typescript-package |
Pure TypeScript utilities with ESM/CJS exports |
font-package |
Web font distribution (WOFF, WOFF2, TTF, OTF, EOT) |
Each generated app/package includes its own sub-generators:
# React package generators
cd packages/my-react-lib
pnpm gen
# Options: create component | create hook | sync exports
# TypeScript package generators
cd packages/my-utils
pnpm gen
# Options: create typescript file | sync exports
# Storybook generators
cd apps/my-storybook
pnpm gen
# Options: create stories| Command | Description |
|---|---|
pnpm build |
Build all packages and apps |
pnpm dev |
Start all apps in development mode |
pnpm test |
Run all tests with Vitest |
pnpm typecheck |
Type check all packages |
pnpm lint |
Lint and auto-fix with ESLint |
pnpm format |
Format code with Prettier |
pnpm clean |
Clean all build artifacts |
pnpm gen |
Run Turbo generators |
pnpm knip |
Detect unused dependencies and exports |
pnpm check-updates |
Check for dependency updates |
| Command | Description |
|---|---|
pnpm gen:all |
Regenerate all example apps and packages |
pnpm gen:apps |
Regenerate all example apps |
pnpm gen:packages |
Regenerate all example packages |
These scripts are useful for testing generator templates after modifications.
Run tasks on specific packages using --filter:
# Run build only on astro-website and its dependencies
pnpm build --filter=astro-website...
# Run build only on astro-website (without dependencies)
pnpm build --filter=astro-website
# Run dev on all packages in apps/
pnpm dev --filter="./apps/*"
# Run tests on all packages except storybook-react
pnpm test --filter="!storybook-react"
# Run typecheck on packages that changed since main branch
pnpm typecheck --filter="[main]"| Filter Pattern | Description |
|---|---|
name |
Exact package name |
name... |
Package and all its dependencies |
...name |
Package and all its dependents |
./path/* |
All packages matching the path glob |
!name |
Exclude a package |
[git-ref] |
Packages changed since git reference |
{./path/*}[main] |
Changed packages in path since main |
Run commands in specific packages:
# Run a script in a specific package
pnpm --filter=astro-website dev
# Add a dependency to a specific package
pnpm --filter=react-package add lodash
# Add a dev dependency to a specific package
pnpm --filter=react-package add -D @types/lodash
# Add a workspace package as dependency
pnpm --filter=astro-website add @myorg/react-package@workspace:*
# Run command in all packages matching pattern
pnpm --filter="@myorg/*" build
# Run command recursively in all packages
pnpm -r exec pwd# Run with verbose output
pnpm build --verbosity=2
# Run without cache
pnpm build --force
# Run with specific concurrency
pnpm build --concurrency=4
# Dry run to see what would be executed
pnpm build --dry-run
# Generate task graph visualization
pnpm build --graph=graph.html
# Continue running even if a task fails
pnpm test --continue
# Run only tasks that have no cache
pnpm build --only- Flat config format (
eslint.config.ts) - TypeScript-aware linting
- React and JSX accessibility rules
- Astro support for
.astrofiles - Storybook rules for story files
- Perfectionist for import/export ordering
- Prettier integration for consistent formatting
- Tailwind CSS plugin for class sorting
- Astro plugin for
.astrofiles - Configured in
prettier.config.ts
Detects unused code and dependencies:
pnpm knipConfiguration in knip.ts with Astro-specific patterns.
- Workspace-aware test configuration
- Root configuration in
vitest.config.ts - Per-package configurations for specific needs
- Testing Library integration for React components
The Dockerfile demonstrates multi-stage builds for production deployment:
# Build astro-website image
docker build --target astro-website-runtime -t astro-website .
# Build storybook-react image
docker build --target storybook-react-runtime -t storybook-react .
# Run containers
docker run -p 3000:3000 astro-website
docker run -p 3001:3001 storybook-react| Stage | Description |
|---|---|
base |
Node.js Alpine with PNPM enabled |
*-build |
Build stage with full dependencies |
*-runtime |
Minimal distroless runtime image |
Features:
- Distroless base images for security
- Non-root user execution
- pnpm deploy for minimal production dependencies
- Build caching for faster rebuilds
The boilerplate includes GitHub Actions workflows demonstrating a complete CI/CD pipeline. These workflows serve as examples that you can adapt for your own projects.
| Workflow | Trigger | Purpose |
|---|---|---|
check-code.yml |
Push to main, feature/**, PRs |
Continuous Integration |
deploy.yml |
Push tag v* |
Continuous Deployment |
Runs on every push and pull request to ensure code quality:
Steps:
1. β¬οΈ Checkout code
2. π¦ Install PNPM & Node.js (from .nvmrc)
3. οΏ½ Restore Turborepo cache
4. π₯ Install dependencies
5. β
Security audit (pnpm audit)
6. π§Ή Unused code detection (knip)
7. π
Lint (ESLint)
8. π§Ό Format check (Prettier)
9. π¨ Type check (TypeScript)
10. π§ͺ Unit tests (Vitest with coverage)
11. ποΈ Build all packages
Features:
- Concurrency control - Cancels duplicate runs on the same branch
- Turborepo cache - Caches
.turbofolder for faster subsequent builds - Auto PNPM version - Uses version from
packageManagerfield in package.json
Triggered when pushing a version tag (e.g., v1.0.0):
Steps:
1. π Verify tag is on main branch
2. π Verify main branch CI is green
3. ποΈ Build & push Docker images (parallel matrix)
Features:
- Concurrency control - Prevents parallel deployments
- Tag verification - Ensures tag is on the main branch
- CI status check - Only deploys if latest CI on main passed
- Matrix strategy - Builds apps in parallel (astro-website, storybook-react)
- Version tags - Images tagged with both
latestand version (e.g.,v1.0.0) - Scoped Docker cache - Separate cache per app for faster builds
# Create and push a version tag to trigger deployment
git tag v1.0.0
git push origin v1.0.0
# Or create an annotated tag with message
git tag -a v1.0.0 -m "Release version 1.0.0"
git push origin v1.0.0Images are pushed to GitHub Container Registry with version tags:
ghcr.io/<owner>/<repo>-astro-website:latest
ghcr.io/<owner>/<repo>-astro-website:v1.0.0
ghcr.io/<owner>/<repo>-storybook-react:latest
ghcr.io/<owner>/<repo>-storybook-react:v1.0.0
When bootstrapping a new project:
- Update workflow triggers - Adjust branch patterns if needed
- Add/remove build targets - Modify Docker build steps for your apps
- Configure secrets -
GITHUB_TOKENis automatic, add others as needed - Adjust Node.js version - Automatically read from
.nvmrc
Note: The example workflows build Docker images for the example apps (
astro-website,storybook-react). After bootstrapping, update the workflows to build your own applications.
Git hooks are managed with Husky and lint-staged in .husky/:
Runs automatically before each commit on staged files only:
- ESLint - Lint and auto-fix
.js,.jsx,.ts,.tsx,.mjs,.cjs,.astrofiles - Prettier - Format all staged files
# .husky/pre-commit
pnpm lint-stagedConfiguration in package.json:
{
"lint-staged": {
"*.{js,jsx,ts,tsx,mjs,cjs,astro}": ["eslint --fix"],
"*": ["prettier --write --ignore-unknown"]
}
}Features:
- Only staged files - Fast, doesn't touch unrelated files
- Auto-rollback - Reverts changes if any task fails
- Parallel execution - Runs tasks in parallel for speed
i18n is powered by Paraglide.js from the inlang ecosystem.
- Settings:
project.inlang/settings.json - Translations:
translations/{locale}.json - Base locale: French (
fr) - Supported locales: French (
fr), English (en)
translations/
βββ en.json # English translations
βββ fr.json # French translations
Each app integrates Paraglide.js for type-safe translations. See individual app READMEs for specific implementation details.
| Tool | Purpose | Why This Choice |
|---|---|---|
| Turborepo | Monorepo build system | Optimized for JS/TS monorepos with intelligent caching, parallel execution, and minimal configuration. Faster than Nx for simple setups. |
| PNPM | Package manager | 3x faster than npm, strict dependency resolution, content-addressable storage saves disk space, native workspace support. |
| TypeScript | Type safety | Catches errors at compile time, enables IDE autocompletion, self-documenting code, essential for large codebases. |
| Node.js 24 | Runtime | LTS version with native ESM support, improved performance, and modern JavaScript features. |
| Tool | Purpose | Why This Choice |
|---|---|---|
| ESLint | Linting | Industry standard, highly configurable, flat config for better performance, extensive plugin ecosystem. |
| Prettier | Code formatting | Opinionated formatter eliminates style debates, integrates with ESLint, supports all project file types. |
| Knip | Unused code detection | Keeps codebase clean by detecting dead code, unused dependencies, and orphaned files. Essential for monorepos. |
| Husky | Git hooks | Zero-dependency, easy setup, ensures code quality before commits reach the repository. |
| Tool | Purpose | Why This Choice |
|---|---|---|
| Vitest | Unit testing | Native ESM support, Vite-powered for speed, Jest-compatible API, built-in TypeScript support, watch mode. |
| Testing Library | Component testing | Tests components as users interact with them, promotes accessibility, framework-agnostic patterns. |
| Tool | Purpose | Why This Choice |
|---|---|---|
| Astro | Web framework | Zero JS by default for performance, island architecture, SSR/SSG flexibility, excellent DX with content collections. |
| React 19 | UI library | Largest ecosystem, concurrent features, Server Components ready, industry standard for component libraries. |
| Tailwind CSS 4 | Styling | CSS-first configuration, no runtime overhead, excellent DX with VS Code extension, design system in CSS. |
| Storybook 10 | Component development | Isolated component development, visual testing, documentation generation, accessibility testing built-in. |
| Tool | Purpose | Why This Choice |
|---|---|---|
| tsdown | TypeScript bundler | Built on esbuild for speed, simple configuration, automatic dual ESM/CJS output, tree-shaking. |
| Vite | Dev server & bundler | Instant HMR, native ESM dev server, Rollup-based production builds, extensive plugin ecosystem. |
| Docker | Containerization | Reproducible builds, distroless images for security, multi-stage builds for minimal image size. |
| Tool | Purpose | Why This Choice |
|---|---|---|
| Paraglide.js | Type-safe i18n | Compile-time translations, fully typed message functions, tiny runtime (~1kb), tree-shakeable, no runtime parsing. |
# Error: The engine "node" is incompatible with this module
nvm use # Use the version specified in .nvmrc# Install PNPM globally
corepack enable
corepack prepare pnpm@latest --activate
# Or install specific version
npm install -g pnpm@10.25.0# Clear PNPM cache and reinstall
pnpm store prune
rm -rf node_modules pnpm-lock.yaml
pnpm install# Clear Turborepo cache
pnpm clean
rm -rf .turbo
pnpm build --force# Ensure you're running from the correct directory
# Root generators:
pnpm gen # From monorepo root
# Package-specific generators:
cd packages/my-package
pnpm gen # From package directory# Ensure Docker is running
docker info
# Build with no cache if issues persist
docker build --no-cache --target astro-website-runtime -t astro-website .# Reinstall Husky hooks
pnpm prepare
# Or manually install
npx husky installIf you encounter issues not covered here:
- Check the GitHub Issues
- Search existing issues before creating a new one
- Provide your Node.js version, PNPM version, and OS when reporting
Contributions are welcome! Here's how to get started:
# Fork and clone the repository
git clone https://github.com/guillaumecatel/monorepo-boilerplate.git
cd monorepo-boilerplate
# Install dependencies
nvm use
pnpm install
# Create a feature branch
git checkout -b feature/my-feature- Follow existing code style - ESLint and Prettier are configured
- Write tests - Add tests for new functionality
- Update documentation - Keep README and inline docs current
- Use conventional commits - Follow the commit message format:
feat:New featuresfix:Bug fixesdocs:Documentation changeschore:Maintenance tasksrefactor:Code refactoringtest:Test additions or fixes
- Ensure all checks pass (
pnpm lint,pnpm test,pnpm typecheck) - Update the README if you've added new features
- Test generator templates by running
pnpm gen:all - Submit a PR with a clear description of changes
When modifying templates in turbo/generators/templates:
# Test by regenerating all examples
pnpm gen:all
# Verify everything still works
pnpm build
pnpm test
pnpm typecheckMIT