← Back to blog

Turborepo in PHP Projects: When It Makes Sense (and When It Doesn't)

“Should you use a monorepo?” The honest answer is the same as for almost everything in software: it depends.

It depends on your team size. It depends on how many projects you have. It depends on whether you share code between them. It depends on your CI/CD pipeline. Depends, depends, depends.

So instead of giving you a universal answer, I’ll give you the contexts where it makes sense — and where it doesn’t.

What’s a Monorepo (in 30 seconds)

A monorepo is a single Git repository that contains multiple projects or packages. Instead of having api, frontend, admin-panel in three separate repos, you have them all in one.

Turborepo is a Vercel tool that optimizes builds and tasks in JavaScript/TypeScript monorepos. It caches results, parallelizes tasks, and only re-runs what changed.

The catch: Turborepo is for the JS/TS ecosystem. What about PHP?

PHP in a Monorepo: The Options

PHP doesn’t have the same monorepo tooling ecosystem as JS, but that doesn’t mean it can’t be done. There are two common approaches:

1. Mixed monorepo (most common in modern projects)

my-project/
  apps/
    api/          # Laravel (PHP)
    web/          # Next.js or Astro
    admin/        # Vue or React
  packages/
    ui/           # Shared components
    types/        # TypeScript types
  turbo.json
  package.json

Turborepo handles the frontend, Laravel lives in its own corner. Works well because each part does its own thing.

2. Pure PHP monorepo (rarer, more opinionated)

Using Composer workspaces (yes, they exist — just not well known):

my-project/
  packages/
    domain/         # Pure business logic
    infrastructure/ # Eloquent, queries, etc.
    api/            # Laravel app
  composer.json     # workspace root

This is more common in hexagonal architectures or DDD where you want real separation between layers.

When It DOES Make Sense

You have a JS frontend + Laravel backend

This is the sweet spot. If you have a Laravel API and a React/Vue/Astro frontend, a monorepo gives you:

  • A single git clone for the whole team
  • Atomic commits that touch both frontend and backend
  • CI/CD that knows exactly what changed and only builds what’s necessary
// turbo.json
{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", ".next/**"]
    },
    "test": {
      "dependsOn": ["build"]
    }
  }
}

Turborepo handles JS, your PHP pipeline (PHPUnit, Pint, etc.) runs separately but in the same repo.

You have multiple apps sharing code

If you have app-client and app-admin that share UI components, TypeScript types, or even PHP helpers — a monorepo eliminates the nightmare of syncing versions across repos.

Without monorepo: change a component → publish package → update dependency in two repos → pray everything works.

With monorepo: change the component, everything updates automatically. Done.

Small team, many projects

With 2-4 people managing 4+ projects, having everything in one place reduces context switching. One place for issues, PRs, and CI/CD.

When It Does NOT Make Sense

Laravel-only project without a separate frontend

If you have a Blade + Livewire app where the frontend lives inside the same Laravel project, there’s nothing to monorepo. You’re adding complexity with zero benefit.

Large teams with separate domains

If you have 20 developers and each team owns their own service, a monorepo can become a bottleneck. Builds take longer, merge conflicts increase, and team autonomy gets complicated.

At that scale you need something more serious: Nx with modules, or simply accepting that separate repos + good release automation works just fine.

When nobody on the team knows how it works

A poorly configured monorepo is worse than separate repos. If you’re adopting this architecture, someone on the team needs to understand how Turborepo, Composer workspaces, and the resulting CI/CD pipeline work.

The tech debt of “we installed it but nobody knows how it works” is real and painful.

The Minimum Setup That Works

If after all this you decide it applies to your context, here’s the minimum to get started:

npx create-turbo@latest my-project
cd my-project
mkdir apps/api
cd apps/api
composer create-project laravel/laravel .

In turbo.json, add tasks only for JS packages. For Laravel, configure your CI pipeline separately (GitHub Actions, for example) pointing to apps/api/.

The trick is not trying to make Turborepo “manage” PHP. Let it do its thing with JS and handle PHP with PHP tools.

Conclusion

Monorepos are a tool, not a universal solution. In Laravel + JS frontend projects with medium-sized teams, they can simplify life a lot. In simple projects or with large, well-separated teams, they can complicate it.

Next time someone asks you “should I use a monorepo?”, you already know the correct answer: it depends.


Are you using monorepos with PHP at your company? I’d love to hear how you structured it — reach out on X/Twitter or contact me directly.