• Blog
  • Docs
  • Pricing
  • We’re hiring!
Log inSign up
ashryanio

ashryanio

index-now

Public
Like
index-now
Home
Code
6
config
1
lib
1
README.md
C
indexnow.cron.ts
H
indexnow.http.ts
H
indexnow.monitor.http.ts
Environment variables
10
Branches
1
Pull requests
Remixes
History
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Sign up now
Code
/
README.md
Code
/
README.md
Search
…
Viewing readonly version of main branch: v191
View latest version
README.md

IndexNow Automation Val

This val automates IndexNow submission by:

  1. Crawling sitemap URLs.
  2. Tracking submission history in project-scoped SQLite.
  3. Submitting only changed URLs with explicit limits at different stages (run URL limit, circuit breaker, and IndexNow POST chunk size).

Quick Start

  1. Read the IndexNow docs (indexnow.org/documentation) and make sure your key file is already hosted on your domain at a public URL like https://www.example.org/<key>.txt.
  2. Add at least one site file in config/sites/*.json with host, sitemapUrl, and keyLocation.
  3. Set required env vars: INDEXNOW_RUN_TOKEN (and INDEXNOW_FORCE_TOKEN if you want force-mode protection).
  4. Open / to confirm the dashboard loads.
  5. Run a safe dry run first: POST /run?dryRun=1 with x-indexnow-token.
  6. After dry run looks correct, enable cron via indexnow.cron.ts for ongoing automation.

Limits (Different Scopes)

  • INDEXNOW_RUN_URL_LIMIT (default 5000): per-site cap for queued changed URLs in a single run.
  • INDEXNOW_CIRCUIT_BREAKER_MAX_URLS (default 200): per-site safety limit for non-force runs; if exceeded, submission is blocked.
  • IndexNow POST payload size (10,000 URLs): protocol hard limit per HTTP request to IndexNow.
  • Monitor query runs (default 50, max 500): number of run-history records returned, not URL count.

Trigger Model

  • indexnow.http.ts: primary HTTP entrypoint.
    • / serves the dashboard UI.
    • /run performs IndexNow submission runs (JSON response).
    • /monitor serves monitor JSON (or dashboard via ?view=dashboard if needed).
  • indexnow.cron.ts: scheduled trigger that calls the HTTP handler at /run.
  • indexnow.monitor.http.ts: monitor implementation module used by indexnow.http.ts.

The recommended setup is a cron trigger every hour for sitemap polling, plus /run for immediate/manual control.

Run Provenance

Run history stores why a run happened using reason:

  • manual_run_endpoint: run came through HTTP POST /run.
  • cron_entrypoint: run came through indexnow.cron.ts.

This is entrypoint provenance. It does not distinguish scheduled cron fires from someone manually running the cron file. To keep provenance meaningful, treat indexnow.cron.ts as scheduler-only and use /run for all manual runs.

Environment Variables

  • INDEXNOW_RUN_TOKEN (required): auth token required for /run (manual and cron).
  • INDEXNOW_FORCE_TOKEN (optional but recommended): separate auth token required when using force=1.
  • INDEXNOW_ENDPOINT (optional): defaults to https://api.indexnow.org/indexnow.
  • INDEXNOW_RUN_URL_LIMIT (optional): defaults to 5000; per-site queue cap per run before batching into IndexNow POSTs.
  • INDEXNOW_MAX_URLS_PER_RUN (legacy alias): still accepted for backward compatibility, but prefer INDEXNOW_RUN_URL_LIMIT.
  • INDEXNOW_CIRCUIT_BREAKER_MAX_URLS (optional): defaults to 200; per-site non-force safety limit that blocks unusually large submissions.
  • INDEXNOW_ALERTS_ENABLED (optional): defaults to enabled; set to 0/false to disable alert emails.
  • INDEXNOW_ALERT_TO_<SITE> (optional): per-site alert recipient email (for example INDEXNOW_ALERT_TO_HANAYOU). If unset, alerts for that site go to the val owner email.

Site Config Files

Site configs live in config/sites/*.json with one site per file. At least one file must exist or the val will throw on startup.

Example: config/sites/hanayou.studio.json

{ "host": "www.hanayou.studio", "sitemapUrl": "https://www.hanayou.studio/sitemap.xml", "keyLocation": "https://www.hanayou.studio/2dc12b205bfe46d19a75077e3991f7ce.txt", "alertToEnvVar": "INDEXNOW_ALERT_TO_HANAYOU", "key": "optional-explicit-key", "includePrefixes": ["/journal/", "/guides/"], "excludePrefixes": ["/tag/", "/author/"] }

Notes:

  • Keep raw email addresses out of config/sites/*.json.
  • Use alertToEnvVar to point to an environment variable that contains the recipient email.
  • If alertToEnvVar is omitted (or env var is empty), the val sends alerts to the default owner email.

HTTP Usage

  • Dashboard: /
  • Run endpoint: /run
  • /run is POST only and requires auth:
    • Authorization: Bearer <INDEXNOW_RUN_TOKEN> or x-indexnow-token: <INDEXNOW_RUN_TOKEN>
  • /run defaults run reason to manual_run_endpoint.
  • x-indexnow-reason: cron_entrypoint is reserved for the cron entrypoint.
  • Dry run: POST /run?dryRun=1
  • Force resubmit currently eligible URLs: POST /run?force=1
    • also requires x-indexnow-force-token: <INDEXNOW_FORCE_TOKEN>
  • On non-dry runs, the val emails per-site recipients when configured (otherwise owner) when:
    • any URLs are successfully submitted, or
    • there are attention conditions (errors, pending, deferred, or circuit breaker blocks).
  • Target a single configured site: POST /run?site=www.hanayou.studio
  • Response includes stage-specific URL arrays:
  • siteRuns[].filteredUrls for URLs that passed filters.
  • siteRuns[].changedUrls for URLs detected as changed.
  • siteRuns[].queuedUrls for changed URLs after run URL-limit capping.
  • siteRuns[].submittedCount counts only HTTP 200 responses.
  • HTTP 202 responses are tracked as pending in siteRuns[].pendingCount.
  • siteRuns[].circuitBreakerTriggered indicates the submission was blocked by the circuit breaker.

Example:

curl -X POST "https://<your-val>.web.val.run/run?dryRun=1&site=www.hanayou.studio" \ -H "x-indexnow-token: <INDEXNOW_RUN_TOKEN>"

Force example:

curl -X POST "https://<your-val>.web.val.run/run?force=1&site=www.hanayou.studio" \ -H "x-indexnow-token: <INDEXNOW_RUN_TOKEN>" \ -H "x-indexnow-force-token: <INDEXNOW_FORCE_TOKEN>"

Monitor Endpoint

  • Path: /monitor on indexnow.http.ts (JSON default)
  • Purpose: IndexNow health snapshot from config + SQLite state
  • Query params:
  • site (optional): limit report to one configured host.
  • runs (optional): recent run-history records per site (default 50, max 500; this is not a URL count).
  • view (optional): dashboard for HTML UI, otherwise JSON.

Response highlights:

  • totals.everSubmitted200Urls: URLs that have ever had a confirmed HTTP 200 submission.
  • totals.upToDateUrls: URLs whose latest sitemap lastmod is already covered by the last successful submission.
  • totals.needsSubmissionUrls: URLs never successfully submitted, or changed since last successful submission.
  • totals.retryPendingUrls: URLs that need submission and whose latest attempt was a non-200/202 failure.
  • sites[].latestRun: latest run summary per site.
  • sites[].recentRuns: recent run history per site.

Dashboard example:

https://<your-val>.web.val.run/?site=www.hanayou.studio&runs=50

History Tracking

SQLite tables:

  • indexnow_url_state_v1: per-URL state (seen/submitted timestamps, lastmod, status).
  • indexnow_run_log_v1: per-run summaries for observability and debugging.

This val uses https://esm.town/v/std/sqlite/main.ts so data is scoped to this val project.

Submission Circuit Breaker

  • Circuit breaker applies only to non-dry, non-force runs.
  • If queued URLs for a site exceed INDEXNOW_CIRCUIT_BREAKER_MAX_URLS, the run is blocked before any IndexNow POST happens.
  • The run logs an error and marks circuitBreakerTriggered: true for that site.
  • To intentionally override for bulk submissions, use force=1 with x-indexnow-force-token.

Ops Runbook

  1. Daily/incident check:
    • Open / dashboard and confirm site health cards are green.
    • Review recent runs for pending, deferred, or Error statuses.
  2. Manual safe run flow:
    • Run dry run first: POST /run?dryRun=1.
    • Review changedCount and queuedCount.
    • If expected, run real submission: POST /run.
  3. If circuit breaker triggers:
    • Confirm the spike is legitimate (content release, migration, etc.).
    • Prefer tuning INDEXNOW_RUN_URL_LIMIT/schedule before forcing.
    • Only then use force=1 with x-indexnow-force-token.
  4. Alert triage:
    • Submission alert with no issues: informational (URLs submitted successfully).
    • Alert with pending: retry/watch next run; investigate endpoint throttling.
    • Alert with deferred: consider run URL-limit tuning or additional runs.
    • Alert with errors/breaker: requires action before trusting indexing progress.
  5. External verification:
    • Use Bing Webmaster Tools to verify ingestion trends (expect lag).
FeaturesVersion controlCode intelligenceCLIMCP
Use cases
TeamsAI agentsSlackGTM
DocsShowcaseTemplatesNewestTrendingAPI examplesNPM packages
PricingNewsletterBlogAboutCareers
We’re hiring!
Brandhi@val.townStatus
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Open Source Pledge
Terms of usePrivacy policyAbuse contact
Β© 2026 Val Town, Inc.