## Core Principle: Writable<> is About Write Access, Not Reactivity **The most important thing to understand:** Everything in CommonTools is reactive by default. The `Writable<>` wrapper in type signatures doesn't enable reactivity—it indicates **write intent**. ### The Rule - **Use `Writable`** in signatures ONLY when you need write access (`.set()`, `.update()`, `.push()`, `.key()`) - **Omit `Writable<>`** for read-only access - the framework automatically provides reactive values ```tsx import { Default, Writable, UI, pattern } from 'commontools' interface Item {} // ✅ Read-only - No Writable<> needed (still reactive!) interface ReadOnlyInput { count: Default; // Just display it (defaults to 0) items: Item[]; // Just map/display userName: string; // Just show it } export const ReadOnly = pattern(({ count, items, userName }) => { return { [UI]: (
Count: {count}
{/* Reactive! */}
User: {userName}
{/* Reactive! */} {items.map(item =>
{item}
)} {/* Reactive! */}
), }; }); // ✅ Write access - Writable<> required interface WritableInput { count: Writable>; // Will call count.set() items: Writable; // Will call items.push() title: Writable; // Will call title.set() } export default pattern(({ count, items, title }) => { return { [UI]: (
{/* Display is still reactive */}
Count: {count}
{/* Can also mutate */} count.set(count.get() + 1)}> Increment {/* Bidirectional binding */} {/* Can also mutate */} items.push({ title: "New" })}> Add Item
), }; }); ```