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

by Bogdan Sikora, Founder & CTO

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:

More articles

Interactive Mobile Experiences: Implementing Scratch Cards in React Native

Revolutionize your React Native apps by adding engaging scratch card functionality. This guide showcases an approach to implementing interactive scratch cards with React Native Skia, enhancing user experience with dynamic, engaging content.

Read more

Bridging Worlds: Integrating Phaser with React for Rich Interactive Experiences

Learn to seamlessly integrate React with Phaser or any other canvas library, unlocking the potential for creating highly interactive and visually rich web applications. This guide provides instructions to bridge the gap between React's UI capabilities and the dynamic graphics of canvas-based libraries.

Read more

Tell us more about your vision