ogygia 0.4

Portable island bindings

A marked import … with { hydrate } rewrites the binding itself into a portable island component. Put several in a dictionary or barrel, pick one into a capitalized binding, and render <Active /> — each stays a real region as long as the usage is at page level.

Do not pass constructors across an island boundary as props — they will not devalue. Keep a small controls island that only receives serializable labels and the active key, and navigate with ?widget= links (works with JS off; the SPA router soft-navs when JS is on). Nesting an island import inside another island degrades to a shared interactive tree — these widgets are imported on the page shell so the selected one is a true region.

notch

Portable island · hydrate: load

Authoring

<script>
  import Pulse from '$lib/Pulse.svelte' with { hydrate: 'load' };
  import Ticker from '$lib/Ticker.svelte' with { hydrate: 'load' };
  import Notch from '$lib/Notch.svelte' with { hydrate: 'load' };
  // Controls island: serializable props only — never pass constructors across.
  import Controls from '$lib/Controls.svelte' with { hydrate: 'load' };

  const registry = { pulse: Pulse, ticker: Ticker, notch: Notch };
  const barrel = [
    { key: 'pulse', label: 'Pulse', Comp: Pulse },
    { key: 'ticker', label: 'Ticker', Comp: Ticker },
    { key: 'notch', label: 'Notch', Comp: Notch }
  ];

  // active comes from load via ?widget= (default first key)
  let { active } = $props();
  const Active = $derived(registry[active]);
  const items = barrel.map(({ key, label }) => ({ key, label }));
</script>

<Controls {active} {items} />
<Active />