Skip to content

JustVugg/nalo

Repository files navigation

Nalo logo

NALO

Open-source Durable Objects for live applications.

Build chat rooms, presence, collaborative cursors, multiplayer sessions, live dashboards, notifications, and user-scoped queues without assembling Redis, WebSockets, sticky sessions, workers, locks, and tables by hand.

durable-objects realtime websocket stateful-runtime live-apps nodejs zero-dependencies

Nalo live room demo

Nalo is a single-node runtime for building realtime features with addressed stateful objects.

Nalo gives every live thing in your app a stable address and a small stateful runtime:

object = compute + durable storage + realtime channel

Use it for AI sessions and other live objects where one address should own state, connected clients, and event ordering.

Why Developers Try It

  • One address per live entity: ws://host/ws/<type>/<id>
  • One object owns state, connected clients, and event ordering
  • No external dependencies for the v0.1 runtime
  • Browser demos included: cursors, chat, todo, counter
  • CLI generator for a self-contained app
  • Tests cover HTTP, WebSocket fanout, persistence, CLI output, and packaging

Install

From this repo:

npm start

As a package:

npm install nalo-runtime
npx nalo demo

Demo

npm start

Open:

http://127.0.0.1:8787/

Best first demo:

http://127.0.0.1:8787/room.html

Open it in two tabs. You get live cursors, presence, chat, and persistent room state backed by one object.

Regenerate the README demo GIF:

npm run demo:gif

Requires ffmpeg on your machine.

Quick API

import { NaloObject } from "./lib/runtime.js";

export class Room extends NaloObject {
  async onConnect(socket) {
    socket.sendJSON({ type: "state", state: await this.state() });
  }

  async onMessage(socket, message) {
    const messages = await this.storage.get("messages", []);
    messages.push(message);
    await this.storage.put("messages", messages);
    this.broadcast({ type: "message", message });
  }

  async state() {
    return {
      messages: await this.storage.get("messages", [])
    };
  }
}

Register it:

runtime.register("room", Room);

Then connect to an addressed object:

WS  /ws/room/lobby
GET /o/room/lobby

CLI

npm start
npm run doctor
node ./bin/nalo.js create my-app

Included Demos

/room.html     collaborative cursors + presence + chat
/counter.html  durable counter broadcast to every tab
/chat.html     persistent chat room
/todo.html     shared todo list

Tests

npm test
npm pack --dry-run

The integration tests open a temporary local HTTP/WebSocket port.

Open Source

Why This Exists

Most realtime apps are secretly stateful. The hard part is not sending a WebSocket frame. The hard part is deciding who owns state, where concurrent events are serialized, how reconnects get current state, and how many services you need before the feature is reliable.

Nalo explores one primitive:

/ws/<type>/<id>

Route everything for that live entity to one durable object. Let the object own the state and the connected clients.

Product Boundary

Nalo v0.1 is a finished single-node runtime:

  • single Node process
  • no external dependencies
  • JSON file persistence with atomic writes
  • in-memory storage adapter for tests/embedded use
  • HTTP object API
  • WebSocket fanout
  • lifecycle hooks: onConnect, onMessage, onDisconnect
  • demo objects and browser demos
  • CLI app generator
  • TypeScript declarations

It is not a distributed cloud runtime yet. The next product line is distribution: object placement, replication, production storage backends, auth, and managed hosting.

About

Open-source Durable Objects for live applications.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Contributors