Targets & observable equivalence
One source, many backends. Every generator lowers the same HTML Next source to a different target, and a single equivalence contract defines when two of those outputs are considered the same program.
Level 1 · reference implementation in progressWhat every generator must do
Whatever the target, a generator turns one HTML Next source into that target's idiom while keeping the same observable behaviour. Concretely, every generator must:
- use the contract's PascalCase name for the exported component;
- preserve the native root element;
- pass through native consumer attributes;
- apply the contract's declared defaults;
- serialize each prop to its target per the contract;
- project children into the default slot;
- import or reference the generated CSS exactly once; and
- produce deterministic output for deterministic input.
CSS output includes the component's transitive @import dependencies. Every target must preserve imported rules' component scope, cascade order, conditions, layers, and source-relative assets, along with document-wide at-rule behavior. A target may bundle or share CSS artifacts; it must not turn component-owned imports into global styles or add stylesheet copies for each instance.
The equivalence contract
Conversion requires an identical user experience. Each framework target uses its framework’s normal rendering, reconciliation and hydration behavior. Exact component lifecycle is not a conversion requirement.
Two executions are equivalent when their lowered native roots share:
- the same namespace and tag name;
- the same effective attributes (order-independent);
- the same assigned property values for explicit property bindings;
- equivalent visible child order and text;
- the same native focus, form, and accessibility semantics; and
- the same validation failures for invalid source.
Hydration markers and development-only attributes are excluded from the comparison, but an adapter must not add semantic wrapper elements.
Framework lifecycle
A framework target may create new DOM nodes or component instances during reconciliation, hydration or outlet changes, as its framework normally does. It does not have to reproduce the native implementation’s setup, mount, unmount or effect timing, or preserve exact DOM or framework instance identity. These internal differences are not conformance failures by themselves.
The user experience remains the requirement: rendered content and placement, interactions, focus, form behavior and accessibility must agree. Tests must check those outcomes rather than require matching lifecycle counts, private ownership trees or object identity with no effect on the user.
Converters should use supported framework primitives. An adapter must not patch framework internals or introduce custom event or view-retention machinery solely to reproduce lifecycle mechanics that have no effect on the user. Integration code that addresses a demonstrated difference in user experience must preserve the framework’s normal event and rendering behavior.
A generator's command line takes a source and an output directory, for example:
component-build button.html --out-dir distNext: see a full source in Examples, or how targets fit the component model in the Overview.