> ## 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.

# Puppeteer

> This guide explains how to deploy a basic Puppeteer site to Sevalla.

[Puppeteer](https://pptr.dev/) is a Node.js library that provides a high-level API for controlling headless Chrome and Chromium browsers. It enables developers to automate browser tasks such as generating PDFs, taking screenshots, scraping websites, running end-to-end tests, and simulating user interactions. With its powerful DevTools integration, Puppeteer offers precise control over page behavior, network requests, and rendering, making it a popular choice for automation, testing, and web content processing.

Puppeteer can only be used on Application Hosting; it cannot be deployed as a static site.

## Configuration

We recommend the following best practices when using Puppeteer with Sevalla:

* Always make sure your processes terminate cleanly by calling `process.exit(0)`
* Implement robust error handling and logging to prevent unwanted crashes.
* Use an external job queue (e.g., Redis, BullMQ) for reliable background processing.
* Add detailed logging to help troubleshoot Puppeteer and browser-related issues.
* Always close browser and page instances to avoid memory leaks and runaway processes.
* Run Puppeteer with the `--no-sandbox` and `--disable-setuid-sandbox` flags in production.
* Test all Puppeteer scripts locally before deploying to Sevalla.

When deploying with a Dockerfile, make sure all required Chrome/Chromium system dependencies are installed.

For generated output, such as PDFs or screenshots, use Sevalla's [object storage](https://docs.sevalla.com/object-storage/overview) or integrate an external storage service like S3.

## Containerization

### Dockerfile

The build for [**Dockerfiles**](https://docs.sevalla.com/applications/build-options/dockerfile) is fully customizable. We recommend using a multi-stage build approach with three stages:

1. `deps` - Install Chromium and Node.js dependencies.
2. `builder` - Build TypeScript code.
3. `runner` - Final production image with minimal size.

Example Dockerfile:

```go expandable theme={null}
# Stage 1: Dependencies
FROM node:lts-alpine AS deps
WORKDIR /app

# Install Chromium and system dependencies
RUN apk add --no-cache \
    chromium \
    nss \
    freetype \
    harfbuzz \
    ca-certificates \
    ttf-freefont

# Configure Puppeteer to use system Chromium
ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true

COPY package*.json ./
RUN npm ci

# Stage 2: Builder
FROM node:lts-alpine AS builder
WORKDIR /app

RUN apk add --no-cache \
    chromium \
    nss \
    freetype \
    harfbuzz \
    ca-certificates \
    ttf-freefont

ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true

COPY --from=deps /app/node_modules ./node_modules
COPY . .

RUN npm run build

# Stage 3: Runner (Production)
FROM node:lts-alpine AS runner
WORKDIR /app

# Install Chromium and dependencies
RUN apk add --no-cache \
    chromium \
    nss \
    freetype \
    harfbuzz \
    ca-certificates \
    ttf-freefont \
    && rm -rf /var/cache/apk/*

ENV NODE_ENV=production
ENV PORT=3000
ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true

# Create non-root user for security
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 puppeteeruser

COPY --from=builder --chown=puppeteeruser:nodejs /app/dist ./dist
COPY --from=builder --chown=puppeteeruser:nodejs /app/package*.json ./
COPY --from=builder --chown=puppeteeruser:nodejs /app/node_modules ./node_modules

USER puppeteeruser

EXPOSE 3000

CMD ["node", "dist/server.js"]
```

This Dockerfile includes the following key features:

1. **Alpine Linux Base**
   * Uses `node:lts-alpine` for minimal image size
   * Includes only essential Chromium dependencies
   * Results in smaller, faster deployments
2. **System Chromium**
   * Installs Chromium via `apk` package manager
   * Avoids duplicate browser downloads
   * More reliable than Puppeteer's bundled Chromium
   * Environment variables configure Puppeteer to use system Chromium:

     ```javascript theme={null}
     PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser
     PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
     ```
3. **Security**
   * Runs as non-root user (`puppeteeruser`)
   * Follows the least-privilege principle
   * Safer for production deployments
4. **Multi-stage Build**
   1. Separates build dependencies from runtime
   2. Reduces final image size
   3. Only production dependencies in the final image

### Nixpacks

[Nixpacks](https://docs.sevalla.com/applications/build-options/nixpacks) automatically detects your project type and creates an optimized build plan. You can customize the **Nixpacks** build process by defining a `nixpacks.toml` file. This allows you to fine-tune how dependencies are installed, how your application is built, and which runtime settings are applied.

The following is an example `nixpacks.toml` configuration:

```javascript theme={null}
[phases.setup]
nixPkgs = ["nodejs_lts", "chromium"]

[phases.install]
cmds = [
  "npm ci"
]

[phases.build]
cmds = [
  "npm run build",
  "npx puppeteer browsers install chrome"
]

[start]
cmd = "node dist/server.js"
```

#### Build phases

**1. Setup phase**

```javascript theme={null}
[phases.setup]
nixPkgs = ["nodejs_lts", "chromium"]
```

* `nodejs_lts`: Installs the latest Node.js.
* `chromium`: Installs system-level Chromium browser and all necessary dependencies. This ensures Chrome/Chromium is available for Puppeteer without manual Dockerfile configuration.

**2. Install phase**

```javascript theme={null}
[phases.install]
cmds = ["npm ci"]
```

* `npm ci:` Performs a clean install using `package-lock.json`. This ensures deterministic, reproducible builds, and it is faster and more reliable than `npm install` for production.

**3. Build phase**

```javascript theme={null}
[phases.build]
cmds = [
  "npm run build",
  "npx puppeteer browsers install chrome"
]
```

* `npm run build`: Compiles TypeScript to JavaScript (outputs to `dist/` directory).
* `npx puppeteer browsers install chrome`: Downloads Chrome browser for Puppeteer.
* Both commands run sequentially during deployment.

**4. Start command**

```javascript theme={null}
[start]
cmd = "node dist/server.js"
```

* Starts the application by running the compiled JavaScript.
* Points to `dist/server.js` (adjust this if your entry point is different, e.g., `dist/index.js`).
