INTERMEDIATE · NEXT.JS

IndexNow in Next.js App Router Implementation

Implementing IndexNow in a Next.js application involves hosting the key file, creating a submission utility, and triggering submissions after content changes. This guide covers the complete implementation for Next.js App Router (13+).

Step 1: Host the Key File

Place your key file in the /public directory Next.js serves everything in /public at the root path.

# File location in your project:
public/d47a82bc1e9f4a3b8c2d5e6f7a8b9c0d.txt
# Accessible at:
https://yourdomain.com/d47a82bc1e9f4a3b8c2d5e6f7a8b9c0d.txt
# File contents (exactly):
d47a82bc1e9f4a3b8c2d5e6f7a8b9c0d

Note: This site itself uses this exact method. The key file at public/68981b2718faa42e6438cc8adda45fa2.txt is already in the project.

Step 2: Create a Submission Utility

// lib/indexnow.ts
export async function
submitToIndexNow(urls: string | string[]): Promise<number> {
const urlList = Array.isArray(urls) ? urls : [urls];
const response = await fetch('https://api.indexnow.org/indexnow', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
host: process.env.NEXT_PUBLIC_DOMAIN ?? 'yourdomain.com',
key: process.env.INDEXNOW_KEY!,
urlList,
}),
});
return response.status;
}
Environment variables: Add INDEXNOW_KEY=your-key-here and NEXT_PUBLIC_DOMAIN=yourdomain.com to your .env.local file. Never commit your key to version control.

Step 3: Trigger Submission After Content Changes

Option A: Server Action (on form submit / revalidation)

// app/actions/publish.ts
'use server';
import { revalidatePath } from 'next/cache';
import { submitToIndexNow } from '@/lib/indexnow';
export async function publishPost(slug: string) {
// ... save to database ...
revalidatePath(`/blog/${slug}`);
await submitToIndexNow(`https://yourdomain.com/blog/${slug}`);
}

Option B: CMS Webhook Handler

// app/api/cms-webhook/route.ts
import { submitToIndexNow } from '@/lib/indexnow';
export async function POST(req: Request) {
const { slug, type } = await req.json();
const url = `https://yourdomain.com/${type}/${slug}`;
await submitToIndexNow(url);
return Response.json({ ok: true });
}

Dynamic Sitemap for Bulk Submission on Deploy

For initial site launches or full re-submissions, extract all URLs from your sitemap and submit them in bulk:

// scripts/bulk-submit.ts (run as npm script)
import { submitToIndexNow } from '../lib/indexnow';
const urls = [/* your URL list */];
// Split into batches of 10,000
for (let i = 0; i < urls.length; i += 10000) {
await submitToIndexNow(urls.slice(i, i + 10000));
}