Next.js — advanced usage

Escape hatches past the binding layer: connectWorker tuning, per-call abort/timeout, shared observables, and pool lifecycle — same APIs under every framework's idiom.

SSR: fields read undefined on the server

The contract only binds in the browser — render fallbacks and let hydration fill in. Trigger run()/runOnce() from event handlers or effects, never during render.

components/Counter.tsxfrontend
'use client';

const count = useSharedValue(counterMemory, 'count');
// Server render: undefined → '…'. Client: binds, then streams writes.
return <span>{count ?? '…'}</span>;

Abort & timeout per call

with() attaches RunOptions to the same client surface. A queued call drops outright; an in-flight call is orphaned — the worker finishes it and the reply is discarded.

frontend
import { TaskAbortedError, TaskTimeoutError } from '@atolljs/core';

const ac = new AbortController();
const request = incidents
  .with({ signal: ac.signal, timeout: 2_000 })
  .queryIncidents(query);

ac.abort();   // rejects with TaskAbortedError

One observable, many components

Each useSharedValue call builds a fresh observe(). Hoist it to module scope and bind via useObservable — subscribers share one field watch.

metrics.tsfrontend
import { observe, shallowEqual } from '@atolljs/core';
import { useObservable } from '@atolljs/nextjs';
import { incidentsMemory } from '@atolljs/incidents';

export const pressure = observe(
  incidentsMemory,
  'state.metrics',
  (m) => ({ open: m.open, critical: m.critical }),
  { equals: shallowEqual },
);

Worker entries under webpack/turbopack

Both bundlers emit a worker chunk only when new Worker(new URL('./x.worker.ts', import.meta.url)) appears inline — never hoist or compute the URL. Contracts imported from workspace sources need resolve aliases + experimental.externalDir (see examples/nextjs/next.config.ts).

next.config.tsfrontend
experimental: { externalDir: true },
turbopack: {
  root: '../../',
  resolveAlias: {
    '@atolljs/core': '../../src/index.ts',
    '@atolljs/nextjs': '../../packages/nextjs/src/index.ts',
    // …
  },
},