Meet Helium, the new home for Feeef themes
A smaller storefront runtime, the same editable theme document, and a clearer boundary between merchant code and the platform.
A merchant should be able to change a heading without shipping a server. A theme developer should be able to build a distinctive shop without owning its hosting. Those two requirements shaped Feeef's template system. They also explain why we're building Helium, our Hono + Preact storefront runtime.
The authoring model stays familiar: TypeScript components become a TemplateData document; the merchant edits that document; the storefront renders it. The change is the engine that reads the document, and how much work it asks the server and browser to do.
A smaller engine around the same idea
Lithium established the document model on Next.js. Helium takes that model into a runtime focused on storefront routes, isolated rendering and browser islands. A theme still contains pages, component instances, editable props, translations and slots. It does not become a separate application deployment.
Theme source Merchant's document Storefront
TSX + meta + locales → pages + props + slots → HTML + browser islands
CLI build visual editor HeliumThat middle column matters. If a product page is one enormous component, the merchant can only edit the controls that component exposes. Separate blocks and slots let them reorder content, hide a field or adjust copy. The new root should preserve that freedom.
Helium templates identify themselves with runtime: "helium" and schemaVersion: 2.
Those fields describe compatibility; changing them on an old theme is not a migration and
does not change where a domain is hosted. Lithium themes need a deliberate compatibility
review before moving across.
Merchant code gets its own boundary
Custom themes contain code. Rendering that code in the same JavaScript environment as the server would make a theme bug a platform problem.
For each executed merchant render, Helium creates a fresh QuickJS runtime inside a bounded worker pool. The guest receives the public data needed for the page. It has no Node globals, filesystem, network access or module loader. CPU, memory and a separate wall-clock watchdog bound the job. The runtime is disposed after it finishes.
This also makes state easier to reason about. A variable changed by one merchant render cannot become the next merchant's module state. Repeated public page results can be reused briefly when their full input snapshot matches; executing a new render still starts fresh.
This boundary concerns server execution. Theme code that runs in a shopper's browser still needs review, especially third-party scripts and data collection.
HTML first, interaction where it belongs
A stylesheet has no reason to become an interactive browser application. A variant picker does. Helium sends server-rendered HTML, then schedules the islands that need browser behavior.
Custom components remain interactive by default. That is intentional: source inspection
cannot reliably recognize every aliased hook, imported wrapper or effect. Authors can mark
a verified static component with hydrate: "never", or choose when an interactive one should
wake up. The hydration guide explains the tradeoffs.
The Helium starter and the Nour, Souk and Rimal packs now explicitly mark their static CSS and footer blocks as server-only. Menus, cart controls, order forms and product selectors keep their browser behavior. The goal is useful JavaScript, with an explicit reason for each piece of it.
The developer loop stays short
Start a Helium theme with the Feeef CLI:
npm install -g @feeef.dev/cli
feeef signin
feeef template init my-theme --helium --store my-shop
cd my-theme
npm run check
npm run build
npm run devChoose the API that owns your store before signing in; the CLI defaults to alpha. A
production store needs feeef config set apiUrl https://api.feeef.org/v1 followed by sign-in.
The hosted draft opens on {slug}.h.feeef.store. It uses real catalog data while customers
continue to see the live document. Walk through the pages and interactions, then publish a
release. Applying that release to the store remains an explicit step.
What we're measuring next
The first origin performance work is documented in Eight thousand stores, one process: a matched comparison, a tenant-churn soak, successful requests rather than error throughput, and the memory peaks alongside the steady-state numbers.
These are engineering results from a local test environment. They do not establish production capacity or browser performance. We still need the Linux deployment measurements and real image, API and checkout paths before making those claims.
For developers, the useful starting point is already concrete: build a Helium theme, keep content editable, and migrate existing work deliberately.