<< All versions

Skill v1.0.1

currentAutomated scan100/100
hypen-lang/hypen/run-examples

+5 new

──Details
PublishedOctober 26, 2026 at 01:54 AM
Content Hashsha256:3ee7c18ba8a0307b...
Git SHAd6fe5dbf95d6
Bump Typepatch
Compare with v1.0.0
──Files
Files (1 file, 5.7 KB)
SKILL.md5.7 KBactive
SKILL.md · 121 lines · 5.7 KB

version: "1.0.1" name: run-examples description: Run the Cloudflare example apps (examples/*) locally with wrangler dev — WASM build, bun file:-symlink workaround, port map, and browser-verification recipe. Use when asked to run, preview, demo, or screenshot the example apps, or when wrangler dev fails with "Could not resolve hypen-engine" / inspector "Address already in use".


Running the Example Apps Locally

The examples under examples/ are Cloudflare Workers built on @hypen-space/cf. They run locally with wrangler dev, but a fresh clone needs three things lined up first. Use the script — it handles all of them:

bash
scripts/dev-examples.sh # launcher set: home-screen, simple, todo, calculator
scripts/dev-examples.sh all # every example
scripts/dev-examples.sh todo # just one
scripts/dev-examples.sh --fresh ... # force-rebuild WASM + package dists

Then open http://localhost:8787 — the home-screen launcher embeds the other examples via HypenApp, so with the default set you can tap through Counter, Todo, and Calculator from the phone UI.

Port map

Ports are load-bearing: the launcher's APPS list (examples/home-screen/cloudflare/src/launcher.ts) points at them.

ExampleDirectoryPort
home-screenexamples/home-screen/cloudflare8787
simple (Counter)examples/simple/cf8788
todoexamples/todo/cloudflare8789
calorie-counterexamples/calorie-counter/cloudflare8790
movie-discoveryexamples/movie-discovery/cloudflare8791
food-orderingexamples/food-ordering/cloudflare8792
socialexamples/social/cloudflare8793
calculatorexamples/calculator/cloudflare8794
hypeflixexamples/hypeflix/cloudflare8795

The three gotchas the script handles

If you run the steps by hand (or are debugging the script), these are the failure modes:

  1. Build artifacts must exist first. Examples depend on

hypen-engine: file:../../../hypen-engine-rs/pkg/web — built by wasm-pack build --target web --out-dir pkg/web --features js,device-broker in hypen-engine-rs/. The @hypen-space/* packages also need their dist/ built (bun run build:core && bun run build:web in hypen-web/, plus bun run build in hypen-web/packages/cf) because wrangler's esbuild resolves the import export condition, which points at dist/.

  1. **bun file: deps are per-file symlink farms, and esbuild realpaths

them.** Imports inside @hypen-space/cf (e.g. import "hypen-engine") then re-resolve from the real hypen-web/packages/cf/ path, where there is no node_modules — the build fails with Could not resolve "hypen-engine" (or an ENOENT for hypen_engine_bg.wasm). Fix: dereference the installed local packages into real copies (cp -rL) after bun install. This only affects local file: development; deployed/npm installs are unaffected.

  1. Concurrent `wrangler dev` instances collide on inspector port 9230.

Pass a distinct --inspector-port per instance or the second one dies with Address already in use (127.0.0.1:9230).

  1. **wrangler dev's ProxyWorker compresses WebSockets with context

takeover.** It is pinned to compatibility date 2023-12-18, so it ignores the examples' no_web_socket_compression flag, and browsers then refuse the device plane (the console warns "device plane disabled on this connection"; uploads are unavailable). The script adds the flag to the installed wrangler's ProxyWorker (patch_wrangler_proxy). Deployed Workers take it from wrangler.jsonc.

The social and home-screen examples also bind R2 buckets (MEDIA, FILES). wrangler dev emulates them under .wrangler/state; a deploy needs wrangler r2 bucket create once per bucket (see each README).

To test the device plane headlessly: a picker is page.waitForEvent("filechooser") after a trusted click on [data-hypen-device="continue"]; an OS file drop is CDP Input.dispatchDragEvent with data.files. For file.save, delete window.showSaveFilePicker in an init script so the <a download> fallback runs.

Also: after rebuilding the engine WASM, refresh each example's node_modules/hypen-engine copy (the script always re-copies it) and restart wrangler. If a Durable Object's persisted state confuses testing, delete the example's .wrangler/ directory — but never while its server is running (wrangler keeps its bundle temp files there).

Verifying in a browser

Headless Chromium is preinstalled in CI/agent containers at /opt/pw-browsers/chromium; drive it with playwright-core:

ts
import { chromium } from "playwright-core";
const browser = await chromium.launch({ executablePath: "/opt/pw-browsers/chromium" });
const page = await browser.newPage();
await page.goto("http://localhost:8787/");
await page.waitForSelector('text="Settings"'); // launcher rendered
await page.screenshot({ path: "home.png" });

Rendered elements carry data-hypen-type attributes (lowercased component names) — useful for structural selectors, e.g. [data-hypen-type='hypenapp'] for embedded app frames.

Deeper (renderer-less) verification

To exercise a template through the real engine without a browser, extract the module's .template / initialState with bun (the packages resolve from source via the bun export condition) and drive the native engine: parse_document → ast_to_ir_node → Engine::set_module + set_render_callback → render_ir_node, then update_state / update_state_sparse and assert on the emitted patches. Watch for __Error elements in Create patches — the engine renders misuse (e.g. a static Grid { } without an array binding) as an __Error node rather than failing loudly.

← v1.0.0All versions