Skip to content

Document the first Web Components integration draft - #35

Open
hnordt wants to merge 3 commits into
mainfrom
codex/web-components-design
Open

Document the first Web Components integration draft#35
hnordt wants to merge 3 commits into
mainfrom
codex/web-components-design

Conversation

@hnordt

@hnordt hnordt commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Summary

  • add design record 0011 for evaluating Custom Elements as a browser interoperability boundary backed by a minimal Preact authoring API
  • document browser/server module separation, light DOM rendering, explicit registration, full-page development reloads, and the illustrative Deno delivery path
  • record lifecycle, failure, concurrency, security, compatibility, maintenance, and evaluation boundaries
  • add the draft record to the design index

Why

The initial Web Components integration draft spans more than the HKElement class itself. It introduces potential public SDK, browser lifecycle, rendering, server delivery, and development-reload contracts that need to remain reviewable before any implementation or support commitment.

Record 0010 now proposes the repository-wide Deno and Web Components direction. This narrower record is subordinate to it: record 0011 preserves one possible HKElement authoring API, a bounded development-delivery sketch, and the evidence needed to evaluate them without advancing record 0010 or claiming implementation.

Impact

This PR changes documentation only. It does not add @hyperkernel/ui, Preact, Deno, Custom Elements, a second production frontend stack, or any runtime behavior.

Classification

  • Kernel — the proposed HKElement surface could become a public SDK contract.
  • Experience — the design concerns component authoring, browser delivery, and development tooling.

This Draft requires experienced human maintainer review before any public SDK contract is adopted.

AI usage

  • Tool: OpenAI Codex
  • Used for: planning, documentation implementation, and conflict resolution
  • Not used for: writing tests
  • Overall level: automated

AI disclosure does not replace the human review required by the classifications above.

Verification

  • npm 11.9.0 on Node.js 24.14.0 installed the locked dependencies with npm ci --ignore-scripts; the normal prepare step was skipped because this environment does not expose node to spawned package scripts
  • Prettier 3.9.6 checked the affected documentation successfully
  • svelte-kit sync completed and svelte-check --tsconfig ./tsconfig.json reported 0 errors and 0 warnings
  • git diff --check passed
  • no runtime or browser tests were run because this PR records an unimplemented design only

Uncertainty and follow-up

  • the reference code is illustrative and unverified in this repository
  • Deno.bundle() is experimental and must be revalidated against the selected Deno version
  • attributes, properties, typed DOM events, update triggers, unmount/reconnect behavior, Shadow DOM, component SSR, and hydration remain open
  • the per-connection filesystem watcher is explicitly limited to a single-client spike
  • advancing the record requires the evidence and experienced human approval listed in its Evaluation section

Related work

PR #32 merged the broader Deno runtime and Web Components frontend direction as design record 0010. This narrower Preact integration draft was merged with the current main, renumbered to 0011, and positioned as subordinate evaluation work.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e74a0ee622

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +405 to +406
Deno.addSignalListener("SIGINT", async () => {
await server.shutdown();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Close SSE streams before awaiting shutdown

When a browser has /dev open, its response stream remains active indefinitely while the watcher loop waits for filesystem events. server.shutdown() is graceful and waits for active requests, so the registered SIGINT handler cannot finish and the development server hangs instead of stopping as the shutdown section claims. Track and close the SSE streams/watchers, or explicitly abort the server, before awaiting shutdown.

AGENTS.md reference: AGENTS.md:L160-L162

Useful? React with 👍 / 👎.


await client.bundle();

const server = Deno.serve((request) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Bind the development server to a trusted interface

When this sketch is run on a shared or untrusted network, Deno.serve() defaults to listening on all interfaces, while the unauthenticated /dev route creates a filesystem watcher for every connection and broadcasts Deno.FsEvent path metadata. This contradicts the record's stated development security boundary and lets remote clients learn local source paths or exhaust watcher/build resources; bind to loopback and gate the development endpoint explicitly.

Useful? React with 👍 / 👎.

Comment on lines +316 to +320
const replacement = result.outputFiles.map(
(output) =>
new File([output.text()], output.hash, {
type: "text/javascript;charset=utf-8",
}),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve bundler output paths in the asset catalog

When Deno.bundle() emits more than one output, such as a dynamically imported chunk or another generated asset, naming every file only by output.hash discards the paths referenced from the generated modules. Those relative imports then request filenames the server never exposes, and non-JavaScript outputs are also mislabeled and injected as module scripts. Preserve the bundler's output paths and MIME types, and emit only the actual entry module in the HTML.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant