Deploy to Cloudflare

Guide to deploy the Next.js SaaS boilerplate to Cloudflare Pages.

To deploy the application to Cloudflare, you need to do the following:

  1. Opt-in to the Edge runtime
  2. Using the Cloudflare Mailer
  3. Switching CMS
  4. Setting Node.js Compatibility Flags
  5. Environment variables
  6. Workarounds

NB: deploying to Cloudflare requires a subscription to the Cloudflare Workers paid service due to the size limitations of the free tier. It starts at $5.

0. Limitations

Before you continue, please evaluate the limitations of the Edge runtime. The Edge runtime does not support all Node.js features, so you may need to adjust your application accordingly.

Cloudflare is cheaper and faster than many other providers, but running your application on Cloudflare Pages means not having access to the vast Node.js ecosystem.

Makerkit uses Cloudflare as a baseline, so you can deploy it to Cloudflare Pages without any issues. However, you will need to keep in mind the limitations of the Workers/Edge runtime when adding new features.

One more thing to consider is that the Edge runtime does run close to your users, but may run far from your database. Consider read replicas or other strategies to reduce latency in all situations.

If your mind is set on using Cloudflare, please follow the instructions below.

1. Opting into the Edge runtime

To opt-in to the Edge runtime, you need to do the following: open the root layout file of your app apps/web/app/layout.tsx and export the const runtime as edge:

export const runtime = 'edge';

This will enable the Edge runtime for your application.

2. Using the Cloudflare Mailer or Resend Mailer

Since the default library nodemailer relies on Node.js, we cannot use it in the Edge runtime. Instead, we will Resend Mailer.

Set up SPF and DKIM records in your DNS settings.

Please follow the Vercel Email documentation to set up the SPF and DKIM records.

Alternatively, you can use the Resend Mailer. Set the MAILER_PROVIDER environment variable to resend in the apps/web/.env file:

MAILER_PROVIDER=resend

And provide the Resend API key:

RESEND_API_KEY=your-api-key

Alternatively, implement your own mailer using the abstract class we provide in the packages/mailers package.

3. Switching CMS

By default, Makerkit uses Keystatic as a CMS. Keystatic's local mode (which relies on the file system) is not supported in the Edge runtime. Therefore, you will need to switch to another CMS or use Keystatic's Github mode - which uses Github as data provider.

At this time, the other CMS supported is WordPress. Set CMS_CLIENT to wordpress in the apps/web/.env file:

CMS_CLIENT=wordpress

Alternatively, use the Keystatic remote mode through Github.

Please check the CMS documentation for more information.

4. Select "apps/web" as path to build

When prompted to select the path to build, select apps/web as the path to build - since our Next.js app is located in the apps/web directory.

If you have multiple apps, you can select the app you want to deploy.

5. Setting Node.js Compatibility Flags

Cloudflare requires you to set the Node.js compatibility flags. Please follow the instructions on the Cloudflare documentation.

Please don't miss this step, as it's crucial for the application to work in the Edge runtime.

6. Environment variables

When adding environment variables, make sure to add all of them from the Cloudflare dashboard instead of the .env file. I cannot understand why, but the Workers did not pick up the environment variables from the .env file. So please do make sure to add all the environment variables from the Cloudflare dashboard.

7. Workarounds

An issue with Cloudflare causes makes it impossible to deploy to Cloudflare Pages without two workarounds:

  1. Monkey-patching the fetch function for Keystatic

Monkey-patching the fetch function

The below is needed if you use Keystatic in Github mode. If you use Wordpress or another CMS, you can skip this step.

Create a new file named mock-workerd-fetch.ts in the packages/cms/keystatic/src directory and add the following code:

function mockWorkerdFetch() { const originalFetch = globalThis.fetch; globalThis.fetch = async function (...args) { try { return await originalFetch.apply(this, args); } catch (e) { if (!args[1] || typeof args[1] !== 'object') throw e; const unimplementedCacheError = e && typeof e === 'object' && 'message' in e && e.message === "The 'cache' field on 'RequestInitializerDict' is not implemented."; if (!unimplementedCacheError) throw e; const newOpts = { ...args[1] }; delete newOpts.cache; return originalFetch.apply(this, [args[0], newOpts]); } }; } mockWorkerdFetch();

Open the file packages/cms/keystatic/src/create-reader.ts and add the following line at the top of the file:

import './mock-workerd-fetch';

Subscribe to our Newsletter
Get the latest updates about React, Remix, Next.js, Firebase, Supabase and Tailwind CSS