Best practices on using Next.js in a TypeScript monorepo

This post mirrors a GitHub Discussion. I’m reposting it here for greater visibility, as it’s been nearly 2 years since I asked for help, and no one from the Vercel team has responded.

Problem

I’ve spent a lot of time researching how to use Next.js v13 in TypeScript monorepo, and I haven’t found much guidance. In fact, I’ve found conflicting recommendations.

Googling “TypeScript monorepo” leads to many articles[1][2] that recommend using TypeScript’s Project References feature (PREFs), which involves enabling composite in tsconfig.json, as well as specifying all TypeScript dependencies in the references field. However, as it says here, PREFs are not compatible with Next.js (given that Next.js uses a different compiler, which at the moment is SWC).

Conversely, googling “Next.js monorepo” leads to several different approaches. The two that stand out are:

  • nextjs-monorepo-example, which employs a plurality of TSConfig files, some which handle building, and others which handle linting (for IDE support)
  • Vercel Solutions’ monorepo example, which uses ES modules to provide selective type resolution

Questions

Given the above, I have the following questions for the Vercel team:

  1. Am I right that PREFs are off-the-table if one wishes to add a Next.js app that depends on other TypeScript packages?
    • Or, one could try to use PREFs in a part of the monorepo that is Next.js-free, but one would then have a difficult time integrating that PREFs-enabled parts in the Next.js app, right? For instance, I can’t think of a way to enable hot reloading in this context.
  2. What would you recommend using between the two approaches mentioned above?
  3. Generally speaking, how can one get the benefits of PREFs (modularity, separation of concerns, cached incremental builds, great debugging UX, etc.) in a Next.js context?

P.S. it seems to me that Next.js forces monorepo users to create a dichotomy between (i) development-only TypeScript configs and (ii) production TypeScript configs. And I think it would be worth documenting this requirement in the TypeScript section in your docs.


  1. The Ultimate Guide to TypeScript Monorepos - DEV Community ↩︎

  2. How to Set Up a TypeScript Monorepo - Earthly Blog ↩︎

Hey there! I’m curious. Have you considered using Turborepo for your monorepo? It seems like it might address the issues you’re running into.