Basics
Welcome to Luna! Let's build your first reactive component.
Quick Start
The fastest way to get started is using the CLI:
npx @luna_ui/luna new myapp
cd myapp
npm install
npm run dev
This creates a new project with Vite and TypeScript configured for Luna.
What is Luna?
Luna is a fine-grained reactive UI framework. Unlike Virtual DOM frameworks that re-render entire component trees, Luna updates only the exact DOM nodes that need to change.
Virtual DOM: State โ Render โ Diff โ Patch
Luna: State โ Direct Update
Your First Component
Here's a simple counter:
import { createSignal } from '@luna_ui/luna';
function Counter() {
// Create reactive state
const [count, setCount] = createSignal(0);
return (
<div>
<p>Count: {count()}</p>
<button onClick={() => setCount(c => c + 1)}>
Increment
</button>
</div>
);
}
Key Concepts
1. Signals Hold State
const [value, setValue] = createSignal(initialValue);
value()- Read the current value (getter)setValue(newValue)- Set a new value (setter)
2. Reading Creates Dependencies
When you call count() inside JSX or an effect, Luna tracks that as a dependency. When count changes, only those specific parts update.
// This text node subscribes to count
<p>Count: {count()}</p>
3. No Re-renders
Unlike React, the component function runs once. Only the reactive parts update:
function Counter() {
console.log("This runs once!"); // Not on every update
const [count, setCount] = createSignal(0);
return <p>Count: {count()}</p>; // Only this text updates
}
Try It
Modify the counter to:
Add a "Decrement" button
Add a "Reset" button that sets count to 0
Display whether the count is even or odd
Solution
function Counter() {
const [count, setCount] = createSignal(0);
return (
<div>
<p>Count: {count()}</p>
<p>{count() % 2 === 0 ? "Even" : "Odd"}</p>
<button onClick={() => setCount(c => c + 1)}>+</button>
<button onClick={() => setCount(c => c - 1)}>-</button>
<button onClick={() => setCount(0)}>Reset</button>
</div>
);
}
Next
Learn more about Signals โ