RouteGraph v1.0.0 is out. It's stable, it's typed, it's not going to rewrite your framework of choice into a decorator soup. → Try it in 90 seconds
DocsHot Reload

Hot Reload

import { RouteWatcher } from '@routegraph/watcher'
 
const watcher = new RouteWatcher(graph, { debounceMs: 150 })
watcher.on('reloaded', (diff) => {
  console.log(`+${diff.added.length} ~${diff.changed.length} -${diff.removed.length}`)
})
watcher.start()

RouteWatcher wraps chokidar. Add, edit, or delete a route file and it reloads the change directly into the running RouteGraph — no server restart, no manual graph.load() call.

What triggers a reload

  • A route file (GET.ts, POST.ts, etc.) is added, changed, or removed.

What doesn’t

  • Non-route files in a route folder (they were never scanned in the first place).
  • Files starting with _ (same reason).
  • Edits to a shared module a route merely imports — the watcher tracks route files, not their dependency graph. Changing _shared/db.ts won’t trigger a reload of routes that import it.

WatcherOptions

OptionTypeDefaultDescription
debounceMsnumber150coalesce rapid saves (editors that write twice) into one reload
ignoredstring | string[] | RegExpextra chokidar ignore patterns

Events

watcher.on('added', (route) => {})
watcher.on('changed', (route) => {})
watcher.on('removed', (route) => {})
watcher.on('reloaded', (diff) => {})   // fires once per debounced batch
watcher.on('error', (err) => {})

Graceful shutdown

process.on('SIGINT', async () => {
  await watcher.stop()
  process.exit(0)
})
process.on('SIGTERM', async () => {
  await watcher.stop()
  process.exit(0)
})

routegraph dev wires all of this up for you automatically — you only reach for RouteWatcher directly if you’re building a custom dev server around @routegraph/core.