I've been building a custom vacuum integration for the past couple of months that started single-vendor (Eufy) and recently went through a full refactor to support multiple brands without touching framework code. Along the way I wrote up the architectural pattern in enough detail that I thought it might be useful to others.
The short version of the pattern: every brand-specific fact — entity IDs, vocabulary, wire payload shape, dropdown options, capability flags, maintenance components — lives in one config dict registered at runtime. Framework code reads from that registry instead of containing brand-specific names or values. Adding a new brand becomes a config-only change.
What the guide covers:
- When to use the pattern (and when not to — including an honest answer to "is one vendor really enough to justify this?")
- Designing the adapter config shape and the rules that keep it portable
- The coordinator pattern for per-entry registry scoping (and why module-level state is a trap even when it works)
- Entity resolution by role, vocabulary and dropdown options, dispatch payload construction, capability gating
- Background state listeners built from adapter-declared entity roles
- Storage decoupling and the vocabulary-drift problem when users switch adapters
- The service-layer auto-resolve pattern for implicit context (e.g.
map_idresolving from the active map sensor when omitted) - Frontend card integration — keeping the card brand-agnostic by reading vocabulary from the backend snapshot
- Discovery services for user-built adapters without a code release
- Anti-patterns, testing strategy, schema versioning and migration, observability and diagnostics
- A minimal working scaffold you can copy
- A full adapter contract reference
It's long. It's the result of actually building the thing and writing down what I wish had existed before I started.
What prompted writing it up:
The HA developer docs cover the API surface well. What they don't cover is how to design for portability from day one — the failure modes of module-level registries, why capabilities should be explicit flags rather than entity-presence probes, how to keep a custom Lovelace card brand-agnostic, or how to version an adapter contract so stored user-built adapters survive framework updates.
I haven't seen this written up specifically for HA custom components. It might be niche, but the people it helps will really need it.
The vacuum integration that the pattern was extracted from: eufy-vacuum-manager
Feedback welcome — especially from anyone who's built multi-device integrations their own way and disagrees with any of the recommendations.