Use IndexNow with Nuxt AI Ready
Nuxt AI Ready does not submit URLs to IndexNow automatically. This recipe submits pages when their indexed Markdown changes.
Use this recipe if your Nuxt site already uses Nuxt AI Ready. Read the IndexNow guide first if you need an overview.
If your CMS or host already submits URLs, keep using that integration. Otherwise, this recipe uses runtime indexing.
The contentChanged flag compares converted Markdown with the stored content hash. First indexing counts as a change. Unchanged pages skip submission.
Generate a Key
Create a 32-character key:
openssl rand -hex 16Set NUXT_INDEX_NOW_KEY to the result in your deployment environment.
Add the key and your production URL to runtime config:
export default defineNuxtConfig({
runtimeConfig: {
indexNowKey: '',
indexNowSiteUrl: 'https://example.com',
},
})Publish the Key
IndexNow uses a public text file to verify site ownership. Add this route:
export default defineEventHandler((event) => {
const { indexNowKey } = useRuntimeConfig(event)
if (!indexNowKey) {
throw createError({
statusCode: 500,
statusMessage: 'IndexNow key is not configured.',
})
}
setResponseHeader(event, 'Content-Type', 'text/plain; charset=utf-8')
return indexNowKey
})Deploy the route before sending URLs. Check that https://example.com/indexnow-key.txt returns only your key.
Submit Changed URLs
Keep the submission code in a server utility:
const INDEX_NOW_ENDPOINT = 'https://api.indexnow.org/indexnow'
const INDEX_NOW_LIMIT = 10_000
export async function submitIndexNow(
paths: string[],
config: { key: string, siteUrl: string },
) {
if (paths.length === 0)
return
if (!config.key)
throw new Error('IndexNow key is not configured.')
const site = new URL(config.siteUrl)
const urls = paths.map((path) => {
const url = new URL(path, `${site.origin}/`)
if (url.origin !== site.origin)
throw new Error(`IndexNow URL must use ${site.origin}.`)
url.hash = ''
return url.href
})
const urlList = [...new Set(urls)]
if (urlList.length > INDEX_NOW_LIMIT)
throw new Error(`IndexNow accepts at most ${INDEX_NOW_LIMIT} URLs per request.`)
await $fetch(INDEX_NOW_ENDPOINT, {
method: 'POST',
body: {
host: site.host,
key: config.key,
keyLocation: new URL('/indexnow-key.txt', site).href,
urlList,
},
})
}The utility rejects URLs from another origin. Connect it to the runtime indexing hook:
export default defineNitroPlugin((nitro) => {
nitro.hooks.hook('ai-ready:page:indexed', async (ctx) => {
if (!ctx.contentChanged)
return
const { indexNowKey, indexNowSiteUrl } = useRuntimeConfig()
await submitIndexNow([ctx.route], {
key: indexNowKey,
siteUrl: indexNowSiteUrl,
})
})
})Enable runtime sync or call the manual indexing utilities to run this hook. The hook has no request event, so the utility receives its configuration explicitly.
Polling only processes pending pages. After publishing an edit, use the authenticated reindex endpoint to check that page again.
Expiring runtimeSync.ttl alone does not mark an indexed page pending.
Only indexed Markdown changes trigger submission. This hook does not detect deleted pages or changes made only during prerendering. Metadata changes trigger submission only when they change the converted Markdown.
The module saves the content hash before this hook runs. If submission fails, re-indexing unchanged content will skip it.
Retry the failed URLs through submitIndexNow directly. Use persistent retry jobs if submissions must survive process restarts.
Static Sites
A static site cannot run these server files. Put the same key in public/indexnow-key.txt.
Use a post-deployment job with a list of changed URLs from your publishing system. Follow the IndexNow request format.
IndexNow supports recent additions, updates, and deletions. Submit deleted URLs after they return 404 or 410.
Do not submit unchanged URLs from the full sitemap. See the IndexNow FAQ.
Responses
IndexNow accepts up to 10,000 URLs per request. This utility rejects a larger batch.
HTTP 200 confirms receipt. HTTP 202 confirms receipt while key validation is pending. Neither guarantees indexing.
If you receive 429, wait before retrying. Honor Retry-After when provided; otherwise use backoff. The utility propagates failures to its caller.
See the IndexNow FAQ for status codes and troubleshooting.