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/webfor the frontendapps/apifor the backendapps/adminfor 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:
| Tool | Detection file | Notes |
|---|---|---|
| Turborepo | turbo.json | Most common with Next.js monorepos |
| Nx | nx.json | Popular for Angular and enterprise projects |
| Lerna | lerna.json | Legacy but still supported |
Detection is priority-ordered: Lerna > Turborepo > Nx. When a monorepo tool is detected, Temps adjusts the install and build commands accordingly.
pnpm workspaces (pnpm-workspace.yaml) are supported through pnpm's package manager detection. Temps detects pnpm-lock.yaml and uses pnpm install --frozen-lockfile automatically. You do not need Turborepo or Nx on top of pnpm workspaces — though many projects use both.
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 manager | Install command | Build command |
|---|---|---|
| pnpm | pnpm install --frozen-lockfile | pnpm turbo build |
| npm | npm ci | npx turbo build |
| yarn | yarn install --frozen-lockfile | yarn turbo build |
| bun | bun install | bun 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 manager | Install command | Build command (with package) |
|---|---|---|
| pnpm | pnpm install --frozen-lockfile | pnpm nx build web |
| npm | npm ci | npx nx build web |
| yarn | yarn install --frozen-lockfile | yarn nx build web |
| bun | bun install | bun 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 manager | Install command | Build command (with scope) |
|---|---|---|
| npm | npx lerna bootstrap | npx lerna run build --scope=web |
| yarn | yarn lerna bootstrap | yarn lerna run build --scope=web |
| pnpm | pnpm lerna bootstrap | pnpm 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:
- Create one Temps project per application — each pointing to a different Root Directory
- Connect all projects to the same Git repository
- 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 project | Root directory | Framework detected | Deployment type |
|---|---|---|---|
my-app-web | apps/web | Next.js | Server container |
my-app-api | apps/api | Express | Server container |
my-app-admin | apps/admin | Vite | Static 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...ornx 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: .
The context: . setting is critical for monorepo Dockerfiles. Without it, the build context is the application subdirectory, and COPY instructions cannot access shared packages or the root lockfile.
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) oroutputs(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.