Next.js
Add monitoring to your Next.js app with App Router. Set up a health endpoint, push heartbeats with Vercel Cron, and embed a status badge.
Prerequisites
- ✓Next.js 13+ with App Router
- ✓Your app deployed and accessible (e.g., on Vercel)
- ✓Submit your service on BlueMonitor (or it auto-registers via the badge)
Health endpoint
Create a simple health endpoint that BlueMonitor will ping every 5 minutes. We check the response status and latency.
app/api/health/route.ts
export async function GET() {
return Response.json({ status: "ok" });
}That's it. BlueMonitor will call GET /api/health and mark your service as operational if it responds with 200 under 3 seconds.
Heartbeat push (optional)
For detailed dependency monitoring, push heartbeats from your service to BlueMonitor. This checks your database, cache, and external APIs internally and reports the results. Requires a BlueMonitor API key.
app/api/cron/heartbeat/route.ts
import { db } from "@/lib/db"; // adjust to your setup
async function checkDependency(name: string, fn: () => Promise<void>) {
const start = Date.now();
try {
await fn();
return { status: "ok" as const, latency: Date.now() - start };
} catch (err) {
return {
status: "error" as const,
latency: Date.now() - start,
message: err instanceof Error ? err.message : "Unknown error",
};
}
}
export async function GET() {
const checks = {
database: await checkDependency("database", async () => {
await db`SELECT 1`;
}),
// redis: await checkDependency("redis", async () => { await redis.ping(); }),
// stripe: await checkDependency("stripe", async () => { await stripe.balance.retrieve(); }),
};
const hasError = Object.values(checks).some((c) => c.status === "error");
const status = hasError ? "error" : "ok";
await fetch("https://www.bluemonitor.org/api/v1/heartbeat", {
method: "POST",
headers: {
Authorization: "Bearer bm_your_api_key",
"Content-Type": "application/json",
},
body: JSON.stringify({
domain: "yourapp.com",
status,
timestamp: new Date().toISOString(),
checks,
}),
});
return Response.json({ ok: true });
}vercel.json
{
"crons": [
{
"path": "/api/cron/heartbeat",
"schedule": "*/5 * * * *"
}
]
}Vercel Cron runs this every 5 minutes. If BlueMonitor stops receiving heartbeats for 10 minutes, your service is marked as down.
Status badge
Add a live status badge to your app. Replace your-domain-com with your domain (dots become dashes).
React component
function StatusBadge({ slug }: { slug: string }) {
return (
<a
href={`https://www.bluemonitor.org/status/${slug}`}
target="_blank"
rel="noopener"
>
<img
src={`https://www.bluemonitor.org/api/badge/${slug}`}
alt="Status on BlueMonitor"
height={36}
/>
</a>
);
}
// Usage: <StatusBadge slug="your-domain-com" />Markdown (README.md)
[](https://www.bluemonitor.org/status/your-domain-com)Environment variables
If using heartbeat push, add your API key to .env.local:
BLUEMONITOR_API_KEY=bm_your_api_keyThen reference it in your heartbeat route: process.env.BLUEMONITOR_API_KEY
Bot tracking
PROTrack which search engines, AI crawlers, and social bots visit your app. Add bot detection to your proxy/middleware to report visits to BlueMonitor. Requires a Pro plan.
Next.js 16+: middleware.ts was renamed to proxy.ts and the exported function from middleware to proxy. For Next.js 13–15, use middleware.ts with the same code but export function middleware instead.
Migrate with: npx @next/codemod@canary middleware-to-proxy .
proxy.ts (Next.js 16+) or middleware.ts (Next.js 13–15)
import { NextRequest, NextResponse } from "next/server";
const BOT_PATTERNS = [
{ pattern: /Googlebot/i, name: "googlebot", category: "search_engine" },
{ pattern: /bingbot/i, name: "bingbot", category: "search_engine" },
{ pattern: /YandexBot/i, name: "yandexbot", category: "search_engine" },
{ pattern: /DuckDuckBot/i, name: "duckduckbot", category: "search_engine" },
{ pattern: /GPTBot/i, name: "gptbot", category: "ai_crawler" },
{ pattern: /ChatGPT-User/i, name: "chatgpt-user", category: "ai_crawler" },
{ pattern: /ClaudeBot/i, name: "claudebot", category: "ai_crawler" },
{ pattern: /anthropic-ai/i, name: "anthropic-ai", category: "ai_crawler" },
{ pattern: /PerplexityBot/i, name: "perplexitybot", category: "ai_crawler" },
{ pattern: /Bytespider/i, name: "bytespider", category: "ai_crawler" },
{ pattern: /CCBot/i, name: "ccbot", category: "ai_crawler" },
{ pattern: /Meta-ExternalAgent/i, name: "meta-externalagent", category: "ai_crawler" },
{ pattern: /Google-Extended/i, name: "google-extended", category: "ai_crawler" },
{ pattern: /Twitterbot/i, name: "twitterbot", category: "social" },
{ pattern: /facebookexternalhit/i, name: "facebookbot", category: "social" },
{ pattern: /LinkedInBot/i, name: "linkedinbot", category: "social" },
{ pattern: /AhrefsBot/i, name: "ahrefsbot", category: "seo" },
{ pattern: /SemrushBot/i, name: "semrushbot", category: "seo" },
{ pattern: /UptimeRobot/i, name: "uptimerobot", category: "monitoring" },
];
function identifyBot(ua: string) {
for (const bot of BOT_PATTERNS) {
if (bot.pattern.test(ua)) return { name: bot.name, category: bot.category };
}
return null;
}
// Next.js 16+: export as "proxy". Next.js 13–15: rename to "middleware".
export async function proxy(request: NextRequest) {
const response = NextResponse.next();
const ua = request.headers.get("user-agent") || "";
const bot = identifyBot(ua);
if (bot) {
// waitUntil keeps the fetch alive without blocking the response
response.waitUntil(
fetch("https://www.bluemonitor.org/api/v1/bot-visits", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BLUEMONITOR_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
domain: "yourapp.com",
visits: [{
bot_name: bot.name,
bot_category: bot.category,
path: request.nextUrl.pathname,
user_agent: ua,
}],
}),
}).catch(() => {})
);
}
return response;
}
export const config = {
matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
};response.waitUntil() keeps the fetch alive without blocking the response — your users get zero added latency. If you already have a proxy.ts (or middleware.ts), add the bot detection to your existing function. View results in your dashboard under Bot Tracking.
Using an AI coding tool?
Paste this URL in Claude, Cursor, or Copilot and it will set up monitoring for your Next.js app automatically.
https://www.bluemonitor.org/llm-nextjs.txtNext steps
- API Reference — explore all endpoints
- Badge Generator — customize your badge with live preview
- Dashboard — set up webhooks for Discord, Slack, or custom alerts