# How to Deploy Next.js 15 App to Cloudflare Workers with GitHub Actions: Complete CI/CD Guide

> Deploy your Next.js 15 app to Cloudflare Workers with GitHub Actions. Automate tests, migrations, and deployments to preview, staging, or production with this comprehensive CI/CD guide.

- Repository: [Muhammad Arifin/fullstack-next-cloudflare](https://github.com/ifindev/fullstack-next-cloudflare)
- Tags: how-to-guide
- Published: 2026-03-03

---

**You can deploy a Next.js 15 application to Cloudflare Workers using a GitHub Actions workflow that runs tests, applies D1 database migrations, and deploys to preview, staging, or production environments based on the branch or pull request.**

The `ifindev/fullstack-next-cloudflare` repository demonstrates a production-ready architecture for running Next.js 15 on Cloudflare's edge runtime. This guide explains how to implement a robust CI/CD pipeline using GitHub Actions to automate testing, database migrations, and multi-environment deployments.

## Prerequisites and Repository Setup

Before implementing the deployment pipeline, ensure your Next.js 15 project is configured for the Cloudflare Workers runtime. The project must use the **@opennextjs/cloudflare** adapter to bridge Next.js server components with the Workers environment.

Key configuration files include:

- **`wrangler.jsonc`**: Defines D1, R2, and Workers AI bindings
- **[`package.json`](https://github.com/ifindev/fullstack-next-cloudflare/blob/main/package.json)**: Contains deployment scripts like `deploy` and `cf-typegen`
- **[`.github/workflows/deploy.yml`](https://github.com/ifindev/fullstack-next-cloudflare/blob/main/.github/workflows/deploy.yml)**: The CI/CD pipeline definition

## Understanding the CI/CD Architecture

The deployment workflow in [`.github/workflows/deploy.yml`](https://github.com/ifindev/fullstack-next-cloudflare/blob/main/.github/workflows/deploy.yml) consists of four specialized jobs that handle different stages of the release process.

### The Test Job

The `test` job runs on every push and pull request to validate code quality before deployment. It executes type checking, linting, and the Next.js build process using pnpm. Only code that passes these checks proceeds to deployment.

### Environment-Specific Deploy Jobs

Three deployment jobs handle different environments:

- **`deploy-preview`**: Creates temporary deployments for pull requests
- **`deploy-staging`**: Deploys the `develop` branch to a staging environment
- **`deploy-production`**: Deploys the `main` branch to production

Each job includes database backups, migration handling, and post-deployment health checks.

## Configuring Cloudflare Resources and Secrets

The pipeline requires specific Cloudflare resources and GitHub Secrets to authenticate and configure the deployment.

### Required GitHub Secrets

Store these sensitive values in your repository settings:

- **`CLOUDFLARE_API_TOKEN`**: Wrangler authentication token with Workers and D1 permissions
- **`CLOUDFLARE_ACCOUNT_ID`**: Your Cloudflare account identifier
- **`BETTER_AUTH_SECRET`**: HMAC secret for session signing
- **`GOOGLE_CLIENT_ID`** and **`GOOGLE_CLIENT_SECRET`**: OAuth credentials for authentication
- **`CLOUDFLARE_R2_URL`**: Public URL of your R2 bucket

### Local Development Configuration

For local testing, create a `.dev.vars` file from the provided `.dev.vars.example` template. This file contains the same variables as the GitHub Secrets but is used by Wrangler during local development with `pnpm run dev:cf`.

## The Deployment Workflow Explained

The GitHub Actions pipeline automates the entire release process from code push to live deployment.

### Preview Deployments on Pull Requests

When developers open pull requests, the `deploy-preview` job automatically provisions a temporary environment. It generates TypeScript bindings with `pnpm run cf-typegen`, applies D1 migrations to the preview database, and deploys using `pnpm run deploy --env preview`. The workflow posts the preview URL directly to the pull request comments.

### Staging and Production Pipelines

For the `develop` and `main` branches, the workflow executes additional safety measures. The `deploy-staging` job creates timestamped D1 backups before applying migrations, then deploys to the staging environment and performs a health check against `/api/todos`. The `deploy-production` job follows the same pattern with stricter pre-deployment checks and verification steps.

### Database Migrations and Backups

Database schema changes are handled safely through Wrangler's D1 migration system. Before applying migrations to staging or production, the workflow executes backup commands to preserve the current database state. This allows for rapid rollback if deployment issues occur.

## Manual Deployment Commands

While the GitHub Actions pipeline handles automated deployments, you can execute the same steps manually using the scripts defined in [`package.json`](https://github.com/ifindev/fullstack-next-cloudflare/blob/main/package.json):

```bash

# Install dependencies

pnpm install --frozen-lockfile

# Generate Cloudflare TypeScript bindings

pnpm run cf-typegen

# Apply migrations locally (optional)

pnpm run db:migrate:local

# Build for Cloudflare Workers

pnpm run build:cf

# Deploy to specific environment

pnpm run deploy --env preview
pnpm run deploy --env staging
pnpm run deploy  # production default

```

These commands utilize `@opennextjs/cloudflare` to package the Next.js application for the Workers runtime and Wrangler to handle resource bindings and deployment.

## Summary

- The `ifindev/fullstack-next-cloudflare` repository provides a complete CI/CD pipeline for deploying Next.js 15 to Cloudflare Workers using GitHub Actions.
- The workflow in [`.github/workflows/deploy.yml`](https://github.com/ifindev/fullstack-next-cloudflare/blob/main/.github/workflows/deploy.yml) handles testing, database migrations, backups, and multi-environment deployments (preview, staging, production).
- Required secrets include `CLOUDFLARE_API_TOKEN`, `CLOUDFLARE_ACCOUNT_ID`, and application-specific variables like `BETTER_AUTH_SECRET` and OAuth credentials.
- The `@opennextjs/cloudflare` adapter bridges Next.js server components with the Cloudflare Workers runtime, configured via `wrangler.jsonc`.

## Frequently Asked Questions

### What is the role of @opennextjs/cloudflare in this deployment setup?

The `@opennextjs/cloudflare` package acts as the bridge between Next.js 15 and the Cloudflare Workers runtime. It packages the Next.js application into a format compatible with Workers, handling server component rendering and API routes within the edge environment. This adapter is invoked through the `pnpm run deploy` command defined in [`package.json`](https://github.com/ifindev/fullstack-next-cloudflare/blob/main/package.json).

### How does the workflow handle database migrations safely?

The GitHub Actions workflow applies D1 database migrations using Wrangler's migration system. For staging and production environments, it first creates timestamped backups of the existing database before applying any schema changes. This backup strategy allows for rapid rollback if the deployment encounters issues, ensuring data integrity throughout the CI/CD process.

### Can I deploy to Cloudflare Workers without using GitHub Actions?

Yes, you can deploy manually using the command line tools provided in the repository. After installing dependencies with `pnpm install`, you can run `pnpm run cf-typegen` to generate TypeScript bindings, `pnpm run build:cf` to build the application, and `pnpm run deploy --env [environment]` to push directly to Cloudflare Workers. However, the GitHub Actions pipeline provides automated testing, migration safety, and multi-environment management that manual deployment lacks.

### What triggers the different deployment environments?

The deployment environment is determined by the Git event type and branch name. Pull requests trigger the `deploy-preview` job to create temporary preview environments. Pushes to the `develop` branch trigger the `deploy-staging` job for pre-production testing. Pushes to the `main` branch trigger the `deploy-production` job for the live application. This branch-based strategy ensures that code progresses through testing stages before reaching production.