clone

a deno framework for local-first web apps that open instantly, work offline and sync when users choose

fix/175-template-quality-pass
lofi / docs / spikes / astro-deno / evidence / 2026-07-15.md
2026-07-15.md 4.4K source

Astro + Deno toolchain evidence — 2026-07-15

Issue: #6
Baseline commit: 0843833
Machine: macOS 26.5.1, Deno 2.9.0, Headless Chrome 150.0.0.0
Pins: Astro 7.0.9, @astrojs/preact 6.0.1, Preact 10.29.7, Jazz 2.0.0-alpha.53

Go decision

Graduate Astro static output with Deno as the only public command runtime. Do not install the Deno Astro adapter until an on-demand route actually exists. The PWA target benefits from a prerendered shell; a server adapter adds runtime modules and deployment choices without serving M1.

Exact command surface

deno task dev
deno task check
deno task test
deno task build
deno task preview

The build produced one prerendered route, wrote a short Git build identity, and ran the nested-dist secret scan. The Deno preview served the retained production output and printed its URL plus build identity. No Node command or global Node installation was used.

Routine check and build disable Jazz's managed development server, so neither command publishes a schema or exposes server secrets to Astro. Development retains automatic schema publication. The production bundle contains no __LOFI_PROTOTYPE__ test probe, and preview serves the web manifest as application/manifest+json.

Two-island and lifecycle result

Two independent client:load Preact roots share one browser-global Jazz database and one query subscription. A write in either root updates both. Reload and explicit client recreation retained OPFS data. Five HMR edits preserved local identity/data and settled after each edit at:

active clients:              1
active component consumers:  2
active vendor subscriptions: 1
active mutation listeners:   1

Two concurrent recreation requests coalesced to one replacement client and returned to the same 1 / 2 / 1 / 1 steady state. Lifecycle tests also defer database initialization past HMR disposal and verify that the obsolete module never attaches its store or mutation listener.

The runtime forwards SIGINT/SIGTERM to Astro so the wrapper does not orphan a development server. Astro 7's agent-detected background mode is disabled inside the stable lofi wrapper; the public command remains foreground and Ctrl-C behaves conventionally.

Startup measurements

Measurement begins at command invocation and ends when Astro prints the usable local URL.

Mode Samples Median Slowest
Cold app caches cleared + --force 1 1,187 ms 1,187 ms
Warm 1,210 / 1,179 / 1,181 / 1,178 / 1,180 ms 1,180 ms 1,210 ms

Astro's internal warm measurements were 886 / 853 / 839 / 828 / 851 ms. The lofi wall time is the contract value because it includes the wrapper. Dependency download was already warm and is not misreported as an uncached project-creation measurement; that belongs to M2's generator.

The final checkout-to-retained-write run took 18,998 ms from deno task dev invocation through a local durability-confirmed write visible in both islands. Reload retained the row and restored the 1 / 2 / 1 / 1 steady state. This validates DX-PROTOTYPE-01's 60-second cached-checkout budget.

npm-compatibility findings

The exact stack passed after retaining these settings:

  • nodeModulesDir: "auto";
  • explicit Preact subpath imports, including jsx-dev-runtime;
  • vite.resolve.noExternal: ["@astrojs/preact"] to resolve Astro's virtual Preact options module;
  • a Preact-aware app tsconfig.json;
  • workspace filesystem allowance for Jazz's Deno npm-cache WASM path;
  • a preseeded internal Jazz app ID to avoid the plugin's first-run .env restart race.

Astro's dependency graph resolves Vite 8.1.4 while the standalone Jazz control remains pinned to Vite 8.0.1. Both passed. Investigation stayed inside Deno; the agreed Node-build fallback was not needed.

A clean-room server control also built and ran with @deno/astro-adapter@0.6.0 when hostname, port, and start were explicit. Static mode is still the M1 choice because no request-time rendering requirement exists.

Contract delta

No public Node fallback is necessary. DX-START-01, DX-BUILD-01, and the M1 part of DX-CMD-01 are validated. DX-HMR-01 uses one underlying subscription per shared query rather than duplicating one per island consumer.