Zones in Action: Structuring Next.js Monorepos for Seamless Integration

In the evolving landscape of web development, the adoption of monorepo architectures has emerged as a pivotal strategy for managing complex projects with multiple interrelated components. Specifically, for Next.js applications, leveraging a monorepo setup offers unparalleled advantages in terms of code reuse, simplified dependency management, and streamlined workflows. This approach not only enhances collaboration across teams but also significantly boosts productivity by centralizing the codebase, making it easier to maintain and update. By consolidating various Next.js applications and packages into a single repository, developers gain the ability to share code effortlessly, enforce consistent coding standards, and reduce the overhead associated with managing multiple repositories. In this article, we will showcase one of the approaches using zones for a seamless client-facing application, highlighting how a monorepo architecture can be effectively employed with Next.js to create a cohesive, scalable, and modular application ecosystem.

Project Directory Structure

The project is structured into two main directories: apps and packages.

apps Directory

This directory contains independent Next.js applications that operate within the same ecosystem:

  • web: The primary application that orchestrates the integration of various zones.
  • docs: A documentation-specific application.
  • store: An e-commerce application for the project.

packages Directory

This directory houses shared resources across different applications:

  • components: Contains a shared codebase including the design system, shared React components, and custom libraries.
  • tsconfig: Holds the TypeScript configuration files.
  • eslint-config-custom: Provides custom ESLint configuration settings.

Zone Configuration

In our architecture, each Next.js application functions as an autonomous zone, with the web application serving as the master zone. It manages zone configurations, ensuring a seamless user experience across different sections of the project without the user being aware of transitioning between zones.

A "zone" refers to a single deployment of a Next.js application. Multiple zones can be merged into a single application through specific configurations, as detailed in the Next.js documentation on Multi Zones.

Example Zone Configuration

Below is an example of how the web application's next.config.js file might be configured to integrate multiple zones:

const {
  DOCS_URL = 'http://localhost:3001',
  STORE_URL = 'http://localhost:3002',
} = process.env

module.exports = {
  transpilePackages: ['@shared/components'],
  async rewrites() {
    return [
      { source: '/:path*', destination: `/:path*` },
      { source: '/docs', destination: `${DOCS_URL}/docs` },
      { source: '/docs/:path*', destination: `${DOCS_URL}/docs/:path*` },
      { source: '/store', destination: `${STORE_URL}/store` },
      { source: '/store/:path*', destination: `${STORE_URL}/store/:path*` },
    ]
  },
}

Each zone is required to set a basePath to facilitate this integration, as demonstrated in the docs application's next.config.js:

module.exports = {
  basePath: '/docs',
}

NPM Workspace Configuration

Utilizing NPM Workspaces significantly streamlines the management of multiple packages within our monorepo. It enables the automatic linking of subprojects and shared dependencies. The root package.json demonstrates a basic workspace configuration that encompasses both the apps and packages directories:

{
  "name": "my-monorepo",
  "version": "1.0.0",
  "workspaces": ["apps/*", "packages/*"]
}

TypeScript and ESLint Configurations

Our project utilizes TypeScript and ESLint to maintain code quality and consistency. We have established a base TypeScript configuration that serves as the foundation for environment-specific configurations. Similarly, our ESLint setup integrates Prettier for code formatting and enforces a standard coding style across the project. TurboRepo

TurboRepo serves as our build system, enhancing the management of our codebase. It facilitates the customization of scripts and the efficient handling of package dependencies.

Additional Resources

For further reading on monorepo concepts and tooling, the following resources are recommended: