RankControl publishes to Next.js sites through a pull model. Your site reads
articles from the Content API and renders them at your own URLs, for example
yoursite.com/blog/article-slug. RankControl never touches your repository
or your host. You add a few files once, and every article after that appears
on its own.
Connect the destination
- Go to Brand Control → Publishing and pick the Headless / Static / Next.js card.
- Enter your site URL and the article path where articles should live, for
example
/blog. If a route already exists at that path, pick a different one so your existing pages are never overwritten. - Click Create destination.
The next screen shows your API key. Copy it right away: it is shown only
this once. You can always mint a new read:content key later under
Settings → API.
Set up your site
The same screen gives you two paths:
- Agent prompt. One copyable prompt for Cursor, Claude Code, or any coding agent working in your repository. It contains the key, the endpoints, and instructions for every file below.
- Manual setup. The same files as copy-paste code blocks.
Either way, your site ends up with:
| File | What it does |
|---|---|
.env.local |
API URL, API key, and revalidate secret |
lib/rankcontrol.ts |
Fetches articles from the Content API |
app/[path]/[slug]/page.tsx |
Renders each article as a native page |
app/api/rankcontrol/revalidate/route.ts |
Lets new articles appear instantly |
next.config.js |
Allows article images from cdn.imgcloud.org |
If your site already lists its own posts, one more snippet merges RankControl articles into your blog index and sitemap.
Publish your first article
The Content API serves published articles only. Planned titles and drafts stay private, so a site you just connected shows an empty list until you publish something. An empty list means the setup works and there is nothing to serve yet.
Open Content in RankControl, pick an article, and publish it. From there:
- The article becomes available on the Content API right away.
- RankControl calls your revalidate route, so the article page and your article list refresh immediately.
- A couple of minutes later, RankControl loads the article on your site to confirm it renders. An article that is not reachable yet is marked Not live yet on the Content screen, and the check retries on its own.
New articles need no deploy. Next.js renders an unknown slug on first request by fetching the Content API. If you skipped the revalidate route, pages refresh on a five minute timer instead.
Count AI crawler visits
AI crawlers (GPTBot, ClaudeBot, PerplexityBot and others) fetch your HTML and stop. They run no JavaScript, so a page script never sees them. A small middleware in your site reports their visits to RankControl, and the AI Crawling screen shows which crawlers read which articles.
Create middleware.ts at the project root. On Next.js 16 name the file
proxy.ts and keep the same export.
import { NextResponse, type NextFetchEvent, type NextRequest } from "next/server";
const AI_BOTS =
/GPTBot|ChatGPT-User|PerplexityBot|ClaudeBot|Claude-Web|anthropic-ai|Google-Extended|Bingbot|Bytespider|CCBot|cohere-ai|Amazonbot|Meta-ExternalAgent|Applebot-Extended|Googlebot/;
export function middleware(req: NextRequest, event: NextFetchEvent) {
const ua = req.headers.get("user-agent") ?? "";
if (AI_BOTS.test(ua)) {
event.waitUntil(
fetch(`${process.env.RANKCONTROL_API_URL}/api/site/crawl`, {
method: "POST",
headers: {
"content-type": "application/json",
"x-rankcontrol-key": process.env.RANKCONTROL_REVALIDATE_SECRET ?? "",
},
body: JSON.stringify({ user_agent: ua, path: req.nextUrl.pathname }),
}).catch(() => {})
);
}
return NextResponse.next();
}
export const config = { matcher: ["/((?!_next/|api/|.*\\..*).*)"] };It uses the two variables you added in .env.local. Only requests from the
crawlers in the list are reported, and the report never blocks a response.
The agent prompt on your destination includes this file as step 8, with the
current crawler list filled in.
Verify the install with one request. It stores nothing:
curl -X POST "$RANKCONTROL_API_URL/api/site/crawl" \
-H "x-rankcontrol-key: $RANKCONTROL_REVALIDATE_SECRET" \
-H "content-type: application/json" \
-d '{"user_agent":"install-check","path":"/","test":true}'The answer is {"ok":true,"test":true}. The destination row then reads
“Crawler snippet: last report just now”, and crawler visits appear under
Analytics → AI Crawling as they happen.
This works on Vercel, Netlify and Cloudflare Pages, for statically generated pages too, because middleware runs on every request. It does not work for a static export served from a storage bucket with no function layer.
Not on Next.js?
Any static site generator works. The API is plain JSON:
GET /api/v1/articleslists your published articles, paginated by cursor.GET /api/v1/articles/{slug}returns one article with its rendered HTML.
Authenticate both with your read:content key as a Bearer header, write
your pages at build time, and set a build hook on the destination. See the
REST API page for the full endpoint reference.