Since Netlify focuses on static site hosting and serverless functions, it doesn"t support hosting Node.js servers in the traditional way. To deploy Strapi on Netlify, you can split the setup into 2 parts:??

  1. Hosting the Strapi API on a backend service and serving the static Strapi admin panel from Netlify.
  2. Packaging Strapi into Netlify Functions for a serverless approach.

This workflow uses Netlify"s strength in serving static assets and an external backend service or functions layer to handle Strapi"s Node.js runtime.

Prerequisites

Before deploying, make sure you have:

  • Node.js with npm or Yarn: Required to run Strapi and manage project dependencies.
  • Strapi project set up locally: Ensures you have a working Strapi instance before deployment.
  • Git repository initialized: Needed for version control and pushing your code to deployment platforms.
  • Netlify CLI installed and logged in: Required to connect your local Strapi project with Netlify for deployment.
  • Production database access (PostgreSQL, MySQL, or MongoDB): Essential for storing data in a live environment, since SQLite (default) isn"t suitable for production.

Part 1: Hosting Strapi API on a Backend Service + Admin Panel on Netlify

Preparing Strapi for Deployment

Strapi defaults to development mode, which is not secure for production. Configure your project to run safely in a production environment.

Create a .env.production File:

A .env.production file centralizes sensitive values (like database credentials, JWT secrets, and app keys) making your production environment secure, consistent, and easy to manage without hardcoding secrets. This keeps secrets secure and consistent without hardcoding them.

code
# .env.production
code
HOST=0.0.0.0
code
PORT=1337
code
APP_KEYS=your_app_keys_here
code
API_TOKEN_SALT=your_api_token_salt_here
code
ADMIN_JWT_SECRET=your_admin_jwt_secret_here
code
DATABASE_CLIENT=postgres
code
DATABASE_HOST=your-db-host.com
code
DATABASE_PORT=5432
code
DATABASE_NAME=strapi_prod
code
DATABASE_USERNAME=db_user
code
DATABASE_PASSWORD=db_password

Explanation:

  • APP_KEYS=your_app_keys_here : Used for session and cookie signing.
  • API_TOKEN_SALT=your_api_token_salt_here : Salt for generating API tokens.

Update package.json File

In your Strapi project, update the package.json file to include production-ready scripts so your host can build and run Strapi correctly:

code
{
code
"scripts": {
code
"develop": "strapi develop",
code
"build": "strapi build",
code
"start": "strapi start"
code
}
code
}

Explanation:

  • ssl : env.bool('DATABASE_SSL', false) : Enables SSL if true (default : false).

Deploying Backend API

The Strapi API cannot run directly on Netlify, since it requires a persistent Node.js runtime. You have two options:

Deploy on a Node.js Host

Use a service like Render, Heroku, or Railway.

Step 1: Push your repository to GitHub.

Step 2: Connect the repository to your hosting service.

Step 3: Configure environment variables from .env.production.

Step 4: Deploy it using:

code
npm run build
code
npm run start

This creates a reliable and production-ready API.

Hosting the Strapi Admin Panel on Netlify

The Strapi Admin Panel is a React Single Page Application. Once built, it becomes static files that Netlify can serve globally for faster load times and seamless Git-based deployment.

Build the Admin Panel

Before Netlify can host the admin panel, Strapi needs to compile the React source into production-ready static files. Running the build command bundles JavaScript, CSS, and assets into the ./build/admin directory so they can be served independently of the backend API.

code
npm run build

→ Output is generated in ./build/admin.

Configure netlify.toml

Netlify needs explicit instructions on where to find the static files and how to build them. The netlify.toml file tells Netlify to run the Strapi build process and publish the compiled admin panel folder, so that deployments work the same way every time.

code
[build]
code
publish = "build/admin"
code
command = "npm run build"

Deploy

Once the files are built and configuration is set, deployment pushes your admin panel to Netlify"s CDN. From there, you can either trigger a manual deploy or connect your GitHub repository for automatic builds and updates whenever you push changes.

code
netlify deploy --prod

Or connect your GitHub repo to Netlify for auto-build and deployment.

Connecting Admin Panel to Backend API

By default, the Strapi Admin Panel doesn"t know where your backend API lives. Since the panel will run from Netlify"s domain and the API from another host, you must explicitly configure the production server settings. This ensures that all admin actions (login, content management, API calls) point to the correct backend service.

Configure API URL in config/env/production/server.js

The server.js config file tells Strapi where it should run in production and which backend URL the Admin Panel should connect to. Without this setting, your admin interface won"t be able to authenticate or fetch content from the deployed backend.

code
module.exports = ({ env }) => ({
code
host: env('HOST', '0.0.0.0'),
code
port: env.int('PORT', 1337),
code
url: env('STRAPI_ADMIN_URL', 'https://your-backend-service.com'),
code
});

Explanation:

  • module.exports = ({ env }) => ({ ... }) : Exports a function that reads environment variables and sets Strapi server configuration.
  • host: env('HOST', '0.0.0.0') : Defines the host where Strapi runs. Defaults to 0.0.0.0 (accessible from all network interfaces).
  • port: env.int('PORT', 1337) : Sets the server port. If not defined in environment variables, it defaults to 1337.

Enable CORS in config/middlewares.js

Since the Admin Panel (hosted on Netlify) and the API (hosted elsewhere) are on different domains, browsers will block requests unless you configure Cross-Origin Resource Sharing (CORS). Enabling CORS here allows trusted origins (your Netlify site) to access the backend securely.

code
module.exports = [
code
'strapi::errors',
code
'strapi::security',
code
{
code
name: 'strapi::cors',
code
config: {
code
enabled: true,
code
origin: ['https://your-netlify-site.netlify.app'],
code
},
code
},
code
'strapi::logger',
code
'strapi::query',
code
'strapi::body',
code
'strapi::session',
code
'strapi::favicon',
code
'strapi::public',
code
];
code

Restart the backend for changes to take effect.

Post-Deployment Configuration

Once your Strapi backend and admin panel are live, align your deployment environment with the same settings you used locally. Without proper environment variables and domain setup, the admin panel may fail to authenticate, connect to the database, or run in production mode. Adding these values in Netlify runs your build securely and consistently, just like in your .env.production file.

  • Add environment variables in Netlify, such as STRAPI_ADMIN_JWT_SECRET, NODE_ENV=production, and Database credentials (if used during admin build).
  • (Optional) Configure a custom domain in Netlify and point DNS records to it.

Testing the Deployment

Deployment will complete after you verify that everything works end to end. Testing ensures that your Netlify-hosted Admin Panel can talk to the backend API, content is saved in the production database, and API routes return the expected data.

Step 1: Open your Netlify-hosted Admin Panel → log in.

Step 2: Create a content type, add entries → confirm they persist in your production database.

Step 3: Test API endpoints:

code
curl https://your-backend-service.com/api/articles
code

Expected: JSON response with your content.

Part 2: Packaging Strapi into Netlify Functions (Experimental)

Deploy API via Netlify Functions (Experimental)

You can package Strapi inside Netlify Functions, but this is not production-ready since serverless environments introduce cold starts, slower performance, and limited features. It"s best suited for quick demos or testing.

Step 1: Create netlify/functions/strapi.js

code
const strapi = require('@strapi/strapi');
code
let app;
code

code
exports.handler = async (event, context) => {
code
if (!app) {
code
app = await strapi().load();
code
}
code
return app.server.app.callback()(event, context);
code
};

Step 2: Update netlify.toml

code
[build]
code
functions = "netlify/functions"
code
command = "npm run build"

Step 3: Deploy with:

code
netlify deploy --prod

Note: This approach is experimental, limited, and best used only for demos or testing.