Public
Rocket launch monitor - FL & TX alerts
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.

Rocket Launch Monitor

Monitors SpaceflightNow's launch schedule and sends email alerts when new launches are announced or existing launch dates/times change for tracked sites.

Tracked Sites

SitePatterns matched
๐ŸŒด Florida (Cape Canaveral / KSC)cape canaveral, kennedy space center, slc-40, lc-39a, lc-39b, slc-41, slc-36, florida
๐Ÿค  Starbase (Boca Chica, TX)starbase, boca chica, orbital launch mount, olm
๐ŸŒŠ Vandenberg (SFB, CA)vandenberg, slc-4e, slc-2, slc-3e

Files

FileTypePurpose
monitor.tsInterval (every 6 hours)Main monitor โ€” fetches schedule, diffs against stored state, sends alert emails
testEmail.tsHTTP endpointManual trigger โ€” sends a snapshot email of all current launches without modifying state

How It Works

  1. monitor.ts runs on a 6-hour interval via Val Town.
  2. It fetches and strips SpaceflightNow's HTML to plain text.
  3. The structured parser extracts launch blocks (date header โ†’ vehicle/mission โ†’ launch time โ†’ launch site โ†’ description).
  4. Each launch is assigned a stable ID: {siteId}-{vehicle}-{mission} (slugified).
  5. The current launch list is diffed against the state stored in a Val Town blob (rocketLaunchMonitorStateV3).
  6. Alerts are sent for:
    • New launches not previously in state
    • Updated launches where the date or time has changed
  7. State is saved back to the blob after every run.

Alert Logic

  • Confidence levels: CONFIRMED (specific date + time), NET (date known, time TBD or "no earlier than"), TBD (only quarter/year known)
  • Launches with past sortDate are filtered out of each run's results (they remain in stored state)
  • The blob accumulates all launches ever seen โ€” past launches are never removed

Resetting State

If you need to force a full re-alert of all current launches (e.g., after fixing a parser bug):

import { blob } from "https://esm.town/v/std/blob"; await blob.delete("rocketLaunchMonitorStateV3");

Run this as a one-off script in Val Town. The next monitor run will treat every launch as new and send a full alert email.

Known Bugs Fixed (April 2026)

Bug 1: </h5> not producing a newline in stripHtml

SpaceflightNow uses paired <h5> elements for the date header and vehicle/mission line. The original stripHtml added \n for </p>, </div>, </li> but not </h5>. If the raw HTML had no whitespace between the closing and opening </h5><h5> tags, the date and vehicle/mission would be concatenated onto one line:

NET April 1 Space Launch System โ€ข Artemis 2

The parser would then:

  • Set rawDate = "NET April 1 Space Launch System โ€ข Artemis 2" (full line)
  • Read the next line ("Launch time: 6:24 p.m. EDT") as the vehicle name
  • Store the launch under a bogus ID like florida-launch-time-624-pm-edt

Result: Artemis II was never alerted correctly. The "new" alert that fired on first detection had a garbled vehicle name.

Fix applied: Added </h[1-6]> to the \n-producing list. Also added a defensive fallback: after matching the date portion with dateHeaderRe, any remaining text on the same line is parsed as vehicle/mission instead of reading the next line.

Bug 2: Inline Updated: skipped the next launch's date header

When "Updated: March 03" appears on one line (as SpaceflightNow renders it), the inner scan loop's handler did:

j++; // advance past "Updated: March 03" while (empty) j++; j++; // intended to skip a separate date line โ€” incorrectly consumed the NEXT launch's date header break;

This caused the launch entry immediately after any updated launch to be silently dropped.

Fix applied: The extra j++ now only fires when Updated: is on its own line (/^updated:\s*$/i). When the date is inline, a single j++ suffices.

Bug 3: siteIdForText in monitor.ts only checked launchSite

testEmail.ts checked both launchSite and description for site pattern matching, but monitor.ts only checked launchSite. Launches where the site name appeared in the description but not the launch site field would be detected by the test email but silently dropped by the monitor.

Fix applied: monitor.ts now passes launchSite + " " + description to siteIdForText, consistent with testEmail.ts.

SpaceflightNow Page Structure (for parser reference)

After HTML stripping, each launch block looks like:

NET April 1
Space Launch System โ€ข Artemis 2

Launch time: 6:24 p.m. EDT (2224 UTC)
Launch site: Launch Complex 39B, Kennedy Space Center

[Description paragraph...]

Updated: March 03

Key structural notes:

  • Date header and vehicle/mission are in separate <h5> elements
  • Updated: appears on a single line (inline with the date, e.g. "Updated: March 03")
  • (UTC time) in launch time is stripped by the cleaner
  • NET prefix means "No Earlier Than" โ€” the date is the floor, not exact