State

Beyond raw signals: field-grained stores, plain storage cells, and seeding island state from the server.

Store — field-grained reactivity

Store(T) generates one signal per struct field. Reading a field subscribes the effect to that field only — updating theme never re-runs effects that read volume:

const Config = struct { theme: []const u8, volume: u8 };
const store = try verve.Store(Config).create(owner, .{ .theme = "dark", .volume = 60 });

store.get(.theme);        // reactive read of one field
store.peek(.volume);      // untracked
store.set(.theme, "light"); // notifies only theme subscribers

StoredValue — non-reactive cell

For values that should live exactly as long as a reactive scope but never trigger updates (caches, handles, buffers):

const cell = try verve.StoredValue([]const u8).create(owner, initial);
cell.get();
cell.getPtr().* = updated; // mutable access
cell.set(value);

Disposed with the owner — no leaks, no manual cleanup.

Island state — server → chunk seeding

Two ways to hand initial data to an island chunk, lighter than the full props codec:

// Named primitives (i32 / f32 / bool / string):
const state = try ctx.islandState(.{ .count = 5, .label = "hi" });

// One serialized struct under a key:
const state2 = try ctx.islandStateStruct("cfg", my_config);

const island = verve.island(ctx, .{ .name = "Widget", .state = state }, inner);

Chunk side:

const count = verve.islandStateValue(i32, "count") orelse 0;

Client persistence

Chunks get localStorage access:

verve.storage.set("seen", "1");
var buf: [8]u8 = undefined;
const v = verve.storage.get("seen", &buf);
verve.storage.remove("seen");

Next: Serialization.