Back to the documentation

HoumeOS architecture: what lives where

Platform updated on 2 November 2026

The HoumeOS architecture in three layers: the kiosk in front of you, the server in your local network and the devices behind it. Who runs the rules, the history and the permissions, what the contract between the layers is and what is not ready yet.

HoumeOS is built as three layers that talk to each other through two explicit contracts. None of the home logic lives in a cloud, and no command decision lives in the tablet.

The three layers

  • Kiosk — the screen in front of you: a React app that shows state and sends commands. It stores no rules, keeps no numbers in the browser and does not decide who is allowed to do what.
  • Local network server (the bridge) — a Node process inside your network. It owns the rules, the home modes, scenes, rooms, profiles with roles and permissions, the event log and the history, plus editing of integrations and pairing.
  • Devices — lamps, blinds, climate zones, water heater, heat pump, smart plug, sensors, cameras, inverter and battery. They speak their own language and reach the server through a state-and-command contract.

The data flow looks like this: devices and controllers publish state to the server over the home/v1/… MQTT topics, Matter nodes come through matter.js (IPv6, UDP 5540, mDNS discovery), and the local server merges everything and hands it to the kiosk as an HTTP snapshot plus an SSE stream. Commands travel the reverse path — from the screen to the server, and from there to the device.

The contract between server and screen

On connect the kiosk asks the server for the whole home with GET /api/state, so it does not wait for the first publish, and then listens to GET /api/stream — a server-sent events stream where every change arrives as a record. After a failure the connection recovers with a backoff from 1 s to 15 s, and if data stops for 15 s the status chip shows retrying instead of going quiet. Ready-made series and log pages come through plain GETs: /api/history, /api/events, /api/alerts. Rules and modes sit under /api/automations* and /api/mode, profiles and sessions under /api/profiles and /api/session, scenes and rooms under /api/scenes and /api/rooms, integrations and pairing under /api/integrations and POST /api/pair.

Authentication uses a token (Authorization: Bearer, and as ?token= for SSE because EventSource cannot set headers). After sign-in the session token lives only in the driver — not in React state and not in localStorage — and travels as x-home-session. The /api/stream feed itself carries data and requires no session.

The contract between server and devices

Topics under the base prefix home/v1 describe every device as state, and commands have their own path: cmd/<type> (home/v1 topics: full list). This is the only definition in the code; formatting is the server's job, and the kiosk knows neither the protocol nor the driver.

What lives on the server, not on the tablet

The rules (trigger, conditions, exceptions, forMs, cooldown, schedules), the scenes, the rooms, the profiles with roles and PINs, the event log and the history, the integrations and their secrets. That is why restarting the tablet changes nothing, and a rule that forbids watering still holds while the internet is down.

Real and simulated devices

The two modes are interchangeable: mock is a local simulation with physics, bridge talks to the server. The choice is VITE_HOME_DRIVER; if bridge is selected without VITE_HOME_BRIDGE_URL, the kiosk falls back to the simulation with a visible warning in the status chip — a broken deployment never stays invisible. The simulator inside the server follows the same MQTT path, so the whole flow can be tested without hardware and without a broker.

What is not ready yet

  • A broker with real devices: the connection code exists, but the mqtt package is not in the dependencies and has not been tested against a real broker.
  • Drivers for Modbus, KNX and ONVIF/RTSP — today those transports are described and verifiable with a real TCP probe, but they do not read the device (protocol support level by transport).
  • HTTPS for access outside the network, and runtime injection of the VITE_* variables.

Do you have a specific installation?

Tell us which devices and over which transports — we answer honestly for every support level.

Integrations and protocols