> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sevalla.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Turborepo

> This guide explains how to deploy a service to Sevalla from a monorepo using Turborepo.

[Turborepo](https://turborepo.com/) is a framework-agnostic tool for efficiently managing monorepos. It includes the following features:

* **Turborepo build system** - Intelligent build orchestration with incremental builds.
* **Parallel execution** - Run tasks across multiple packages simultaneously with automatic CPU optimization.
* **Task pipelines** - Define dependencies between tasks to ensure optimal execution order.
* **Workspace management** - Organize multiple packages and apps in a single repository.
* **Incremental adoption** - Add Turborepo to existing monorepos without refactoring.
* **Selective task execution** - Run tasks only for packages affected by your changes.
* **TypeScript support** - Full TypeScript configuration across all workspaces.
* **Framework agnostic** - Works with Next.js, React, Vue, Express, and any JavaScript/TypeScript framework.

## Configuration

In Sevalla, each application instance can host only a single app. Therefore, in Monorepos with workspace dependencies (`packages/*`), your services must be built from the repository root directory to access all workspace packages and ensure all dependencies resolve correctly.\
To do this, all you need to do is ensure that your `build` and `start` commands are specific to the service you wish to deploy. Refer to our examples in the containerization section for guidance on how to achieve this.

### Environment variable types

* `globalEnv`: Variables that apply to every task and invalidate the cache when changed. Use these for settings that impact all builds, such as`NODE_ENV`, `DATABASE_URL`.
* **Task-specific** `env`: Variables scoped to individual tasks only. These help avoid unnecessary cache invalidation by limiting their impact to the tasks that actually use them.
* **Framework variables**: Variables like `NEXT_PUBLIC_*`, `VITE_*`, or `REACT_APP_*` are automatically detected by Turborepo and will invalidate the cache when modified. Use these for client-exposed configuration.
* `passThroughEnv`: Variables that are passed to tasks but do not affect cache keys. Ideal for runtime-only values that should not trigger new builds, such as secrets or tokens that don’t alter the build output.

## Containerization

### Dockerfile

You must create separate Dockerfiles for each application, the web frontend, and the API backend, located in the repository’s root directory. After creating each application in Sevalla, [assign the correct Dockerfile](https://docs.sevalla.com/applications/settings#build-strategy) to the corresponding service within **Applications** > ***application name*** > **Settings** > **Update build strategy**. Inside each Dockerfile, make sure to use the appropriate build and start commands defined in that application's `package.json`.

Example Dockerfile for the web frontend:

```javascript expandable theme={null}
# Dockerfile for Next.js Web App
# Production-ready build for deploying web app separately

FROM node:lts-alpine AS base

# Enable pnpm
RUN corepack enable && corepack prepare pnpm@9.15.4 --activate

# Builder stage - install dependencies and build
FROM base AS builder

WORKDIR /app

# Copy root package files
COPY package.json pnpm-lock.yaml* pnpm-workspace.yaml ./

# Copy all package.json files to install workspace dependencies
COPY apps/web/package.json ./apps/web/package.json
COPY apps/api/package.json ./apps/api/package.json
COPY packages/ui/package.json ./packages/ui/package.json
COPY packages/typescript-config/package.json ./packages/typescript-config/package.json

# Install all dependencies (needed for workspace)
RUN pnpm install

# Copy source files
COPY . .

# Build web app and its dependencies using Turborepo
RUN pnpm build:web

# Runner stage - minimal production image
FROM base AS runner

WORKDIR /app

ENV NODE_ENV=production
ENV PORT=3000

# Create non-root user
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

# Copy Next.js standalone build
# The standalone output includes all dependencies needed to run
# (No need to copy node_modules - standalone bundles everything)
COPY --from=builder --chown=nextjs:nodejs /app/apps/web/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/apps/web/.next/static ./apps/web/.next/static
COPY --from=builder --chown=nextjs:nodejs /app/apps/web/public ./apps/web/public

USER nextjs

EXPOSE 3000

# Start Next.js standalone server
CMD ["node", "apps/web/server.js"]
```

Example Dockerfile for the API backend:

```javascript expandable theme={null}
# Dockerfile for Express API
# Production-ready build for deploying API separately

FROM node:lts-alpine AS base

# Enable pnpm
RUN corepack enable && corepack prepare pnpm@9.15.4 --activate

# Builder stage - install dependencies and build
FROM base AS builder

WORKDIR /app

# Copy root package files
COPY package.json pnpm-lock.yaml* pnpm-workspace.yaml ./

# Copy all package.json files to install workspace dependencies
COPY apps/web/package.json ./apps/web/package.json
COPY apps/api/package.json ./apps/api/package.json
COPY packages/ui/package.json ./packages/ui/package.json
COPY packages/typescript-config/package.json ./packages/typescript-config/package.json

# Install all dependencies (needed for workspace)
RUN pnpm install

# Copy source files
COPY . .

# Build API using Turborepo
RUN pnpm build:api

# Runner stage - minimal production image
FROM base AS runner

WORKDIR /app

ENV NODE_ENV=production
ENV PORT=3001

# Create non-root user
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 apiuser

# Copy built API
COPY --from=builder --chown=apiuser:nodejs /app/apps/api/dist ./dist
COPY --from=builder --chown=apiuser:nodejs /app/apps/api/package.json ./package.json

# Copy only production node_modules from builder
# This avoids workspace resolution issues and is more efficient
COPY --from=builder --chown=apiuser:nodejs /app/node_modules ./node_modules

USER apiuser

EXPOSE 3001

# Start Express API
CMD ["node", "dist/index.js"]
```

### Nixpacks

You must create a separate `nixpacks.toml` file for each application, the web frontend, and the API backend, located in the repository’s root directory.

Alternatively, you can use the following Nixpacks environment variables to specify the build and start commands:

* `NIXPACKS_BUILD_CMD`
* `NIXPACKS_START_CMD`

You can control the Node.js version used during the build by using an `.nvmrc` file, the `engines` field in `package.json`, or the `NIXPACKS_NODE_VERSION` environment variable. If none are set, Nixpacks defaults to Node.js 18.

Example `nixpacks.toml` file for the web frontend:

```javascript theme={null}
[phases.build]
cmds = [
  "pnpm build:web"
]

[start]
cmd = "pnpm start:web"
```

Example `nixpacks.toml` file for the API backend:

```javascript theme={null}
[phases.build]
cmds = [
  "pnpm build:api"
]

[start]
cmd = "pnpm start:api"
```
