Introduction
A Headless CMS decouples content management from presentation, offering maximum flexibility for modern architectures. In 2026, combining Strapi with Next.js enables rich experiences while maintaining optimal performance. This advanced tutorial guides you through configuring complex content types, implementing secure webhooks for ISR revalidation, custom JWT authentication and deploying to Vercel. You'll learn how to avoid common pitfalls related to scalability and API security. Each step includes ready-to-use functional code.
Prerequisites
- Node.js 20+ and npm
- Advanced knowledge of TypeScript and Next.js App Router
- Strapi Cloud account or self-hosted server
- PostgreSQL database
- Vercel account for deployment
Initialize Strapi Project
npx create-strapi-app@latest cms-strapi --quickstart
cd cms-strapi
npm run developThis command creates a complete Strapi project with SQLite by default. Switch to PostgreSQL in production for scalability. Develop mode activates the admin panel at http://localhost:1337.
Article Content Type Definition
{
"kind": "collectionType",
"collectionName": "articles",
"info": { "singularName": "article", "pluralName": "articles" },
"attributes": {
"title": { "type": "string", "required": true },
"slug": { "type": "uid", "targetField": "title" },
"content": { "type": "richtext" },
"publishedAt": { "type": "datetime" }
}
}This schema defines an Article type with auto-generated slug. Strapi automatically generates REST and GraphQL endpoints. Add relations and components for more complex structures.
Permissions and JWT Configuration
export default {
'users-permissions': {
config: {
jwt: { expiresIn: '7d' },
register: { allowedFields: ['username', 'email'] }
}
}
};Customize JWT duration and allowed fields during registration. This strengthens security for APIs consumed by Next.js.
Webhook for ISR Revalidation
import { Strapi } from '@strapi/strapi';
export default ({ strapi }: { strapi: Strapi }) => ({
async handle(ctx) {
const { model, entry } = ctx.request.body;
if (model === 'api::article.article') {
await fetch(`${process.env.NEXT_URL}/api/revalidate?secret=${process.env.REVALIDATE_SECRET}&slug=${entry.slug}`);
}
ctx.send({ success: true });
}
});This custom controller triggers ISR revalidation in Next.js when an article is published. Protect it with a shared secret.
Revalidation API Route in Next.js
import { NextRequest, NextResponse } from 'next/server';
import { revalidatePath } from 'next/cache';
export async function GET(request: NextRequest) {
const secret = request.nextUrl.searchParams.get('secret');
const slug = request.nextUrl.searchParams.get('slug');
if (secret !== process.env.REVALIDATE_SECRET) return NextResponse.json({ message: 'Invalid' }, { status: 401 });
revalidatePath(`/articles/${slug}`);
return NextResponse.json({ revalidated: true });
}This secure route allows Strapi to purge the ISR cache. Use it only for critical content updates.
Strapi Client in Next.js
const STRAPI_URL = process.env.STRAPI_URL;
const STRAPI_TOKEN = process.env.STRAPI_API_TOKEN;
export async function fetchArticles() {
const res = await fetch(`${STRAPI_URL}/api/articles?populate=*`, {
headers: { Authorization: `Bearer ${STRAPI_TOKEN}` }
});
return res.json();
}This TypeScript client centralizes API calls using the Strapi API token. Handle errors and caching for production.
Best Practices
- Always use API tokens limited to the minimum required permissions
- Implement webhook validation with HMAC signature
- Configure pagination and filters on the Strapi side to prevent data leaks
- Use separate environments (dev/staging/prod) with isolated databases
- Monitor performance with Strapi logs and Vercel metrics
Common Errors to Avoid
- Forgetting to configure CORS on Strapi, blocking Next.js requests
- Exposing secrets in client code without environment variables
- Neglecting deep relation handling (populate) causing N+1 queries
- Failing to test webhooks locally with ngrok before deployment
Going Further
Explore advanced Strapi plugins like i18n or custom middleware. Discover our Learni courses to deepen your Headless CMS architecture knowledge.