Skip to content

Templates

Templating with JSX is familiar, but more flexible than other frameworks. You don’t have to worry about scope, hooks or lifecycle events, and cleanup happens automagically.

There’s no virtual DOM and mount is a one-time operation. Each element tracks its own dependencies and updates only when necessary, similar to SolidJS’ granular updates.

You can access the DOM directly, without the need for refs or special APIs, making it easy to integrate with existing libraries or custom elements.

import { signal } from '@hellajs/core';
import { mount } from '@hellajs/dom';
const Counter = () => {
const count = signal(0);
{/* ⚠️ Attach functions for reactivity, don't call them */}
return (
<button onclick={() => count(count() + 1)}>{count}</button>
);
};
mount(Counter, "#counter");

Components are simply functions that return a JSX element. Any element using a signal or derived function for text content or attributes becomes reactive.

It doesn’t matter if you use upper or lower case names, or if you use a function or arrow function.

import { signal } from '@hellajs/core';
import { mount } from '@hellajs/dom';
const Counter = (props, children) => {
// Signals are reactive
const count = signal(props.count);
// Derived functions using signals are also reactive
const doubleCount = () => count() * 2;
const countClass = () => count() % 2 === 0 ? 'even' : 'odd';
return (
{/* ⚠️ Attach functions for reactivity, don't call them */}
<div class={countClass}>
<p>Count: {count}</p>
<p>Double Count: {doubleCount}</p>
<button onclick={() => count(count() + 1)}>{count}</button>
{children}
</div>
);
};
mount(Counter, "#counter");

Since functions make elements dynamic, you can use plain JavaScript conditionals like if or switch, just return an element.

const isShown = signal(true);
//...
<div>
{() => isShown() ? <p>Shown</p> : ""}
</div>

Use the forEach function to work with dynamic lists that need more complex operations.

import { signal } from '@hellajs/core';
import { forEach } from '@hellajs/dom';
const users = signal([
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
]);
<ul>
{forEach(users, (user) =>
<li key={user.id}>User {user.name}</li>
)}
</ul>

Components are just functions, so you can use them dynamically without any extra modules.

import { signal } from '@hellajs/core';
const components = {
profile: () => Profile(props),
settings: () => Settings(props),
};
const active = signal("profile");
//...
<main>
{() => components[active()]}
</main>

For dynamic HTML elements, JSX supports dynamic tag creation:

import { signal } from '@hellajs/core';
const TagComponent = signal('div');
//...
<main>
<TagComponent>This is dynamic</TagComponent>
</main>