Deploy Monorepos

Temps supports deploying individual applications from monorepo repositories. Point each Temps project at the subdirectory containing your app, and Temps handles framework detection, builds, and deployments independently for each one.


How monorepos work on Temps

A monorepo contains multiple applications and shared packages in a single Git repository. To deploy from a monorepo, you create a separate Temps project for each application and configure the project directory to point at the correct subdirectory.

Typical monorepo structure

my-monorepo/
  apps/
    web/          <-- Temps project 1 (Next.js)
    api/          <-- Temps project 2 (Express)
    admin/        <-- Temps project 3 (Vite)
  packages/
    ui/           <-- Shared component library
    config/       <-- Shared config
  turbo.json
  package.json
  pnpm-lock.yaml

Each Temps project builds independently. When you push to the repository, all projects connected to it receive a deployment trigger. Each project builds from its own subdirectory.

Setting the project directory

When creating a project in Temps, set the Root Directory field to the subdirectory containing your application:

  • apps/web for the frontend
  • apps/api for the backend
  • apps/admin for the admin panel

Temps clones the entire repository but uses your specified directory as the build context. Framework detection, dependency installation, and builds all run relative to this directory.


Monorepo tool detection

Temps detects your monorepo tool from marker files in the repository root:

ToolDetection fileNotes
Turborepoturbo.jsonMost common with Next.js monorepos
Nxnx.jsonPopular for Angular and enterprise projects
Lernalerna.jsonLegacy but still supported

Detection is priority-ordered: Lerna > Turborepo > Nx. When a monorepo tool is detected, Temps adjusts the install and build commands accordingly.


Turborepo

Turborepo is detected when turbo.json exists in the repository root. Temps uses turbo build scoped to your project directory.

Project setup

turbo.json

{
  "$schema": "https://turbo.build/schema.json",
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "dist/**"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}

apps/web/package.json

{
  "name": "web",
  "scripts": {
    "build": "next build",
    "start": "next start"
  },
  "dependencies": {
    "next": "^16.0.0",
    "ui": "workspace:*"
  }
}

Create a Temps project with Root Directory set to apps/web. Temps detects Next.js in the subdirectory and Turborepo at the root.

Generated build commands

When Turborepo is detected, the generated Dockerfile uses:

Package managerInstall commandBuild command
pnpmpnpm install --frozen-lockfilepnpm turbo build
npmnpm cinpx turbo build
yarnyarn install --frozen-lockfileyarn turbo build
bunbun installbun turbo build

Turborepo's dependsOn: ["^build"] ensures shared packages build first, then the target app builds. Turbo's built-in caching skips unchanged packages.


Nx

Nx is detected when nx.json exists in the repository root. Build commands are scoped to the target project.

Generated build commands

Package managerInstall commandBuild command (with package)
pnpmpnpm install --frozen-lockfilepnpm nx build web
npmnpm cinpx nx build web
yarnyarn install --frozen-lockfileyarn nx build web
bunbun installbun nx build web

Where web is the project slug (derived from the directory name or package.json name).

For Nx, the build command targets a specific project, so only the affected project and its dependencies are built.


Lerna

Lerna is detected when lerna.json exists in the repository root.

Generated build commands

Package managerInstall commandBuild command (with scope)
npmnpx lerna bootstrapnpx lerna run build --scope=web
yarnyarn lerna bootstrapyarn lerna run build --scope=web
pnpmpnpm lerna bootstrappnpm lerna run build --scope=web

Lerna scopes the build to the target package using --scope.


pnpm workspaces

pnpm workspaces work without an additional monorepo tool. Temps detects pnpm-lock.yaml and uses pnpm commands:

pnpm-workspace.yaml

packages:
  - 'apps/*'
  - 'packages/*'

Set the Root Directory to your app subdirectory (e.g. apps/web). Temps installs all workspace dependencies from the root lockfile, then builds the specific application.

To override the build command for pnpm workspaces, use .temps.yaml:

.temps.yaml (in apps/web/)

build:
  install_command: pnpm install --frozen-lockfile
  build_command: pnpm --filter web build

Deploying multiple apps

To deploy multiple applications from the same repository:

  1. Create one Temps project per application — each pointing to a different Root Directory
  2. Connect all projects to the same Git repository
  3. Push to the repository — all projects receive a deployment trigger

Each project builds and deploys independently. A failure in apps/api does not affect the deployment of apps/web.

Example: three apps from one repo

Temps projectRoot directoryFramework detectedDeployment type
my-app-webapps/webNext.jsServer container
my-app-apiapps/apiExpressServer container
my-app-adminapps/adminViteStatic files

Each project can have its own environment variables, custom domain, and deployment settings.


Custom build configuration

Override the auto-detected commands with .temps.yaml in the application subdirectory:

apps/web/.temps.yaml

build:
  install_command: pnpm install --frozen-lockfile
  build_command: pnpm turbo build --filter=web...
  output_dir: .next
  • Name
    install_command
    Type
    string
    Description

    Override dependency installation. Useful when the auto-detected monorepo command does not match your workflow.

  • Name
    build_command
    Type
    string
    Description

    Override the build step. Use monorepo-aware commands like turbo build --filter=web... or nx build web.

  • Name
    output_dir
    Type
    string
    Description

    Override the expected build output directory.


Using a custom Dockerfile

For complex monorepos where auto-detection is not sufficient, add a Dockerfile to your application subdirectory:

apps/web/Dockerfile

FROM node:22-alpine AS base
RUN corepack enable

# Install dependencies from the workspace root
FROM base AS deps
WORKDIR /app
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
COPY apps/web/package.json ./apps/web/
COPY packages/ui/package.json ./packages/ui/
COPY packages/config/package.json ./packages/config/
RUN pnpm install --frozen-lockfile

# Build
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY --from=deps /app/apps/web/node_modules ./apps/web/node_modules
COPY . .
RUN pnpm turbo build --filter=web...

# Production
FROM base AS runner
WORKDIR /app/apps/web
COPY --from=builder /app/apps/web/.next ./.next
COPY --from=builder /app/apps/web/package.json ./
COPY --from=builder /app/apps/web/node_modules ./node_modules

EXPOSE 3000
CMD ["pnpm", "start"]

When using a custom Dockerfile with a monorepo, set the build context to the repository root so that COPY . . includes all workspace packages:

apps/web/.temps.yaml

build:
  dockerfile: apps/web/Dockerfile
  context: .

Troubleshooting

Build fails with "workspace package not found"

The build context is set to the application subdirectory, but your Dockerfile references files from the repository root or other packages. Set build.context: . in .temps.yaml to make the full repository available during the build.

Wrong build command

If Temps uses npm commands but your project uses pnpm, check that pnpm-lock.yaml exists in the repository root. Temps detects the package manager from lockfiles. If the lockfile is missing from Git (check .gitignore), Temps falls back to npm.

Shared package changes not picked up

Turborepo and Nx both use caching. If a change to a shared package is not reflected in the build output, verify that:

  • The shared package is listed in dependsOn (Turborepo) or as a dependency (Nx)
  • The build output directories are included in outputs (Turborepo) or outputs (Nx)
  • The cache is not stale — Temps builds in a fresh environment each time, so local cache issues do not apply

Multiple lockfiles

If your repository has lockfiles in both the root and subdirectories, Temps uses the one in the build context. For monorepos, the lockfile should be at the root. Remove subdirectory lockfiles to avoid confusion.


What to explore next

Framework auto-detection reference Custom Dockerfile deployments Configure environment variables Preview deployments per branch

Was this page helpful?