← Val TownCONTENT HISTORYWHAT CHANGED · RULE-BASED ANALYSIS
Update to Val Town
Snapshot Sep 30, 2026 · 22:50 UTC · version 3.0.0
Collection source: not recorded for this historical snapshot.
First saved snapshot
No earlier snapshot is available to establish a change.
Compare saved observations
Download comparison JSONFull technical diff · 0 changed fields
Full snapshot data
{
"name": "cron-and-intervals",
"description": "Use when building a val that runs on a schedule — periodic jobs, recurring tasks, polling, cron jobs, monitoring, alerting. Covers the interval handler signature, cron expressions, the UTC timezone constraint, and the `lastRunAt` pattern for detecting new items since the previous run.",
"included_files": [],
"skill_md_contents": "---\nname: cron-and-intervals\ndescription: Use when building a val that runs on a schedule — periodic jobs, recurring tasks, polling, cron jobs, monitoring, alerting. Covers the interval handler signature, cron expressions, the UTC timezone constraint, and the `lastRunAt` pattern for detecting new items since the previous run.\n---\n\n# Cron / Interval Vals\n\nInterval vals (`fileType: \"interval\"`) run on a recurring schedule defined by a cron expression. Use them for polling external APIs, sending reminders, running cleanups, generating reports, or any work that should happen on a clock rather than in response to a request.\n\n## Basic handler\n\n```ts\n// Learn more: https://docs.val.town/vals/cron/\nexport default async function (interval: Interval) {\n // interval.lastRunAt: Date | undefined\n console.log(interval);\n}\n```\n\nThe file must have an `export` — `export default` for the handler.\n\n## Timezone\n\n**Cron expressions run in UTC.** Convert any human-readable schedule (e.g. \"9am Eastern\") to UTC before writing the cron expression. Daylight savings is not handled — pick a UTC time that's close enough year-round.\n\n## The `lastRunAt` pattern\n\n`interval.lastRunAt` is the timestamp of the previous successful run (or `undefined` on the first run). Use it to fetch only items created since the last run, instead of re-scanning everything:\n\n```ts\nexport default async function (interval: Interval) {\n const since = interval.lastRunAt ?? new Date(Date.now() - 24 * 60 * 60 * 1000);\n const newItems = await fetchItemsSince(since);\n for (const item of newItems) {\n await handle(item);\n }\n}\n```\n\nThis makes the val idempotent against missed runs and avoids reprocessing.\n\n## Reading and updating the schedule\n\n- `read_interval_settings` — fetch the current cron expression and active state of an interval file.\n- `write_interval_settings` — change the cron expression or pause/resume an interval.\n\n## When to skip a template\n\nFor simple scheduled jobs, create a new val with a single `interval`-type file directly — no template needed. Templates are for more complex shapes (dashboards, AI agents, webhook + UI combos).\n\n## Verifying changes\n\nAfter editing an interval val, use `run_file` to invoke the handler manually instead of waiting for the next scheduled run.\n"
}SHA-256: acdfe645d0e3f28dc026b5aebaa929c9b54dccdfb14ac12c6a8a8638bee2f05a