Zero-UI
← Back to docs/Architecture Decisions – Zero-UI Home Automation (2025)

Architecture Decisions – Zero-UI Home Automation (2025)

Purpose of This File

This document records deliberate architectural decisions made for the Zero-UI Home Automation project.

It exists to:

  • Prevent regression into cloud-heavy or UI-driven designs
  • Give future humans and AI systems context for why things are the way they are
  • Establish non-negotiable constraints for all future code and configuration

This file answers “why,” not “how.”


Decision 001 — Local-First Is Mandatory

Decision:
All real-time automation logic must run on-prem.

Rationale:
Cloud latency, outages, API changes, and vendor lock-in break family trust faster than any bug.

Implications:

  • Cloud APIs may be used only for non-critical state
  • Internet loss must not prevent lighting, security, or basic automation
  • Local polling is preferred over push APIs when available

Rejected Alternatives:

  • Cloud-first automation platforms
  • Vendor-hosted rule engines

Decision 002 — Home Assistant Is the Single Brain

Decision:
Home Assistant is the authoritative logic engine.

Rationale:
HA provides:

  • Local execution
  • Mature integrations
  • Deterministic automation
  • Strong ecosystem without mandatory cloud dependence

Implications:

  • No parallel automation logic in SmartThings, Apple Home, or vendor apps
  • All logic flows through HA, even if exposed elsewhere

Rejected Alternatives:

  • SmartThings as primary brain
  • Apple Home automations beyond trivial UI bindings

Decision 003 — Apple Home Is the Only Family UI

Decision:
Apple Home is the exclusive interface for non-technical users.

Rationale:

  • Familiar
  • Stable
  • No training required
  • Works across iPhone, iPad, Apple TV, HomePod

Implications:

  • HA dashboards are operator-only
  • Any feature that requires HA UI interaction is not “family-ready”
  • Devices exposed to Apple Home must be calm, minimal, and curated

Rejected Alternatives:

  • Wall tablets as primary UI
  • Custom dashboards for family members

Decision 004 — Physical Controls Always Win

Decision:
Physical switches and sensors override automation logic.

Rationale:
Humans trust tactile feedback.
Nothing destroys confidence faster than a system that “fights back.”

Implications:

  • Automations must yield to manual interaction
  • No automation may disable or intercept physical controls
  • Lighting logic must tolerate manual overrides gracefully

Rejected Alternatives:

  • Scene-only lighting
  • Software-exclusive control

Decision 005 — Hardwired Sensors Are First-Class Citizens

Decision:
Existing hardwired motion and door sensors are retained and modernized.

Rationale:
They are:

  • Faster
  • More reliable
  • Battery-free
  • Immune to RF congestion

Implications:

  • Konnected + ESPHome becomes a core platform component
  • Wired sensors drive occupancy and presence logic
  • Wireless sensors are supplemental, not foundational

Rejected Alternatives:

  • Full replacement with battery-powered sensors

Decision 006 — MQTT as the Internal Event Bus

Decision:
MQTT is used as the central message transport.

Rationale:

  • Loose coupling between systems
  • Scales cleanly
  • Human-readable debugging
  • Excellent fit for sensors, vehicles, and energy assets

Implications:

  • No hidden point-to-point logic
  • State changes should be publish/subscribe where possible
  • AI systems may observe without interfering

Rejected Alternatives:

  • REST-only integrations
  • Vendor-specific messaging

Decision 007 — Cameras Are Sensors, Not Entertainment

Decision:
Cameras exist to provide situational awareness, not constant viewing.

Rationale:

  • Continuous video feeds increase cognitive load
  • False notifications destroy trust
  • AI should filter reality before humans see it

Implications:

  • PoE cameras preferred
  • Local NVR required
  • AI detection must suppress noise
  • Silence is better than uncertainty

Rejected Alternatives:

  • Cloud-only camera ecosystems
  • Motion-only alerts without classification

Decision 008 — AI Reduces Noise, Not Adds Features

Decision:
AI is used strictly for filtering and classification.

Rationale:
The goal is fewer notifications, not more “smart” behavior.

Implications:

  • Person > package > vehicle detection only
  • No “experimental” AI-driven automations
  • AI failure must default to silence

Rejected Alternatives:

  • AI-generated automations
  • Predictive behavior without explicit rules

Decision 009 — Energy Systems Inform, They Do Not Nag

Decision:
Energy data is contextual intelligence, not a notification source.

Rationale:
Energy systems change slowly; humans should not be interrupted.

Implications:

  • Energy dashboards are operator-only
  • Automations may adapt silently (load shifting)
  • Alerts only for true anomalies (outages, failures)

Rejected Alternatives:

  • Frequent energy alerts
  • User-driven energy micromanagement

Decision 010 — Containers Over Bare Metal Services

Decision:
All core services run in Docker containers.

Rationale:

  • Reproducibility
  • Isolation
  • Simplified recovery
  • Clear dependency boundaries

Implications:

  • No “snowflake” host configs
  • All state persisted via volumes
  • Services restart safely without human intervention

Rejected Alternatives:

  • Manual systemd services
  • VM sprawl

Decision 011 — Stability Over Novelty

Decision:
Stable, boring technology is preferred over cutting-edge features.

Rationale:
This is a house, not a demo lab.

Implications:

  • No beta firmware in production
  • Upgrades planned, not impulsive
  • If it works, it stays

Rejected Alternatives:

  • Feature-chasing
  • Experimental integrations in core systems

Decision 012 — Failure Must Be Predictable

Decision:
Every automation must have an understood failure mode.

Rationale:
Unpredictable systems erode trust.

Implications:

  • Automations fail “dark and quiet”
  • No cascading dependencies
  • No automation required for safety-critical behavior

Rejected Alternatives:

  • Hard dependencies between unrelated systems

Decision 013 — Reverse Proxy & Subdomain Ingress

Decision:
All external access terminates at Nginx Proxy Manager (NPM) with name-based routing on the Docker network. Private services do not expose host ports.

Rationale:
Centralized TLS, clean domain model, least-privilege exposure, and simpler recovery. Avoids port collisions and accidental public exposure.

Implications:

  • Router forwards 80/443 → NPM only (no 3000/port pinholes)
  • Services attach to nginx-proxy_default; NPM forwards by container name
  • Subdomains map to services: teamlewis.co (portal), docs.teamlewis.co (docs), ai.teamlewis.co (Open WebUI), ha.teamlewis.co (Home Assistant), cam.teamlewis.co (NVR)
  • Remove host port mappings for private services (e.g., Open WebUI 8080 only)
  • Let’s Encrypt issued per host; Force SSL, HTTP/2, HSTS enabled

Rejected Alternatives:

  • Mixed host-port and reverse-proxy ingress
  • Wild west per-service random ports

Summary Principle

The system exists to disappear.

If users think about it, something has already gone wrong.

This document is authoritative.
Any future implementation that conflicts with these decisions must be revised or rejected.