Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.vertz.dev/llms.txt

Use this file to discover all available pages before exploring further.

import.meta.hot is typed as ImportMetaHot | undefined as soon as any file in your app imports from one of the client-runtime subpaths (vertz/ui, vertz/ui/components, vertz/ui-primitives, vertz/ui-auth). Their declarations carry a triple-slash reference that auto-loads the vertz/client augmentation.

Explicit opt-in (optional)

If a file uses import.meta.hot without importing from any of those subpaths (e.g. a standalone client entry that only imports from @vertz/ui directly), wire the types up explicitly. Pick the subpath that matches what you install:
// tsconfig.json — apps on the full framework
{
  "compilerOptions": {
    "types": ["vertz/client"],
  },
}
// tsconfig.json — UI-only consumers (no `vertz` dependency)
{
  "compilerOptions": {
    "types": ["@vertz/ui/client"],
  },
}
Or, per-file:
/// <reference types="vertz/client" />
// or: /// <reference types="@vertz/ui/client" />
import.meta.hot?.accept();
Both subpaths resolve to the same augmentation — vertz/client re-exports @vertz/ui/client via a triple-slash reference, so they cannot drift. Newly-scaffolded apps (via create-vertz-app) already include the vertz/client tsconfig entry.

The ImportMetaHot surface

MemberDescription
accept()Self-accept — this module handles its own HMR updates.
accept(cb)Self-accept with a callback receiving the new module.
accept(deps, cb?)Accept updates for specific dependency paths.
dispose(cb)Runs before this module is replaced. Receives a persistent data record.
dataRecord<string, unknown> — persisted across HMR updates in the same session.
invalidate(message?)Mark this module as unable to apply an update; triggers a full reload with the message.
decline()Opt out of HMR for this module. The next update targeting it falls back to a full reload.
on(event, cb)Subscribe to an HMR runtime event (see below).
off(event, cb)Remove a previously-registered listener (must be the same callback reference).

Why hot is | undefined

HMR is only active under vtz dev. Production builds and SSR have no hot object — so always optional-chain:
import.meta.hot?.accept();
This is the same shape Vite uses and matches what the Bun build plugin actually emits (if (import.meta.hot) import.meta.hot.accept();).

Narrowing data

data is typed Record<string, unknown> for safety. Cast at the use site rather than using an any type globally:
import.meta.hot?.dispose((data) => {
  data.lastCount = 42;
});

const prev = import.meta.hot?.data.lastCount as number | undefined;

Events

hot.on(event, cb) subscribes to runtime events. Each event delivers a typed payload:
EventPayloadWhen it fires
vertz:beforeUpdate{ module: string }Before a module is re-imported for an HMR update.
vertz:afterUpdate{ module: string }After a module has been re-imported and Fast Refresh has run.
vertz:beforeFullReload{ reason?: string }Before location.reload() is invoked (any cause).
vertz:invalidate{ module: string; message?: string }Another module called hot.invalidate().
vertz:error{ module: string; error: unknown }An HMR update failed to apply.
import.meta.hot?.on('vertz:beforeUpdate', (p) => {
  console.log('about to update', p.module);
});

Decline vs invalidate

Both fall back to a full page reload, but at different times:
  • decline() marks a module as “do not try HMR.” The next time the server pushes an update that includes this module, the client performs a full reload instead of a hot swap. Use when a module holds state that can’t be re-created safely (e.g., a global WebSocket).
  • invalidate(message?) triggers a full reload immediately. Use from inside an accept() callback when you discover at runtime that the new module can’t take over (e.g., a new dependency version is incompatible with live state).

Runtime behavior

Under vtz dev, the compiler rewrites import.meta.hot references to a runtime hot-context lookup. In production (no HMR runtime present) the lookup is undefined, so import.meta.hot?.* remains a no-op — safe in all environments.

What’s not here

send() (custom client → server events) and prune() (cleanup when a module is no longer imported anywhere) are not implemented yet. They require bidirectional WebSocket support and module-removal tracking respectively; tracked for a follow-up.