Install Qlyne on a Next.js app
For a Next.js app on Vercel, or on any host that runs Next.js, without Cloudflare. Qlyne runs as the app’s middleware: the same rules as the Cloudflare connector, decided before each page and API route, with the waiting room, the challenge, rate limits, blocked addresses, AI crawlers, login protection and access gates.
1. Add the file and the middleware
Section titled “1. Add the file and the middleware”In the dashboard, open your site, Connector, “Install on Next.js”, and click Download qlyne-next.mjs. The file already carries your site ID, the Qlyne address and the key that checks the rules. Put it at the root of the project, next to package.json.
Create proxy.js at the root too (Next.js 16; on Next.js 13 to 15 the file is middleware.js, with the same content):
import { qlyne } from './qlyne-next.mjs';
export default qlyne();export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'] };The matcher keeps Next.js’s own files out, so they don’t count as visits. If the project already has a middleware, call Qlyne first and keep yours for what Qlyne lets through:
import { qlyne } from './qlyne-next.mjs';
const protect = qlyne();
export default async function proxy(request, event) { const response = await protect(request, event); if (!response.headers.get('x-middleware-next')) return response; // blocked, challenged or sent to the waiting room return yourMiddleware(request, event);}2. Add the secret and deploy
Section titled “2. Add the secret and deploy”Add the environment variable QLYNE_SECRET with the connector secret (in Connector, “Generate secret”). On Vercel: Settings, Environment Variables, for Production and Preview. Then deploy.
Leave the mode on “Observe only” at first and check the last 24 hours in the site Overview. When the numbers make sense, switch to “Enforce” in Connector. Changes reach the middleware within a minute, with no new deploy.
What works and what doesn’t
Section titled “What works and what doesn’t”A middleware decides before the app answers, but never sees the answer. So:
| Rule | On Next.js |
|---|---|
| Waiting room, challenge, under attack mode | Yes |
| Blocked and trusted addresses, Tor, your rules | Yes; country comes from Vercel (x-vercel-ip-country), the network (ASN) is unknown, so a rule on it never matches |
| AI crawlers | Blocked by user agent; the AI section of robots.txt is not added |
| Rate limits | Counted by the Qlyne server, adding up every instance of your app (one call to Qlyne on limited routes, about tens of milliseconds); if it doesn’t answer in time, each instance counts on its own until it’s back. qlyne({ rateLimit: 'memory' }) keeps the count in each instance only |
| Login protection, access gates, scanner trap, managed rules (WAF) | Yes; the WAF reads form and JSON bodies up to 16 KB from a copy, so your app still gets the whole request |
| Protected forms | No: the middleware can’t add the hidden fields to the page. Use the form captcha |
| Security headers and CSP | Added to every response; the grade in the dashboard needs Cloudflare or the proxy |
| Signals to your app | Yes, as request headers (Qlyne-Country, Qlyne-Leaked-Password…) |
| Bot score | Yes, once the script is in the layout (below); the decoy page is served with a rewrite |
| Shared reputation | Yes, by the IP Vercel gives |
Read the signals in a route handler or server component with headers() from next/headers.
Bot score
Section titled “Bot score”The middleware can’t add the bot score script to your pages, so put it in the root layout (app/layout.js), inside <head>:
<script src="/__qlyne/s.js" async></script>The middleware serves the script and takes its summary at /__qlyne/s; the matcher above already covers both paths. With the bot score off in the dashboard, they go to your app, which answers 404, and nothing else changes. What the score does is in the Cloudflare guide.
The visitor’s IP
Section titled “The visitor’s IP”On Vercel the middleware reads the IP from x-real-ip and x-forwarded-for, which Vercel sets and the visitor can’t forge. On your own server, make sure the reverse proxy in front of Next.js (nginx, Caddy) overwrites those headers with the real address; otherwise a visitor could send a fake one and dodge the per-IP rules.
Updating
Section titled “Updating”The version is on the first line of the file. To update, download it again, replace it and deploy. Your rules stay in the dashboard; the file only carries the code.