A room at the centre, its devices in a ring around it: tap to toggle, swipe to change rooms.
A radial control hub for smart home and shortcut apps: the current room sits in a large centre disc with its devices on a ring of smaller discs joined by soft bridges. Tap a device to switch it, press and hold for its controls, swipe the centre to change rooms while the ring re-deals, and speak or type a command from the dock.
$199 once, every piece included. See how installing works · Sign in
SwiftUI source you own, built on Apple frameworks only.
Velvet (style). Your agent builds around this screen in the same design.
Smart Home App (template)
How it behaves, what it handles, and the decisions behind it.
The current room sits in a large centre disc with its temperature and humidity. Up to eight devices sit on a ring around it, each joined to the room by a soft bridge that pinches in the middle, so the hub reads as one piece rather than nine buttons. A device that is on is a solid block with its outlined glyph in the block's ink; one that is off is a pale surface disc with a hairline. Tap a disc to switch it, press and hold for its controls, and swipe the centre sideways to move to the next room while the ring re-deals from the middle with a short stagger.
Under the hub, the dock puts a keyboard and the cameras either side of a wide block capsule textured with a dot matrix. Tap the capsule and the dots ripple like a voice level while the transcript lands in a chip above it.
[HubRoom] with up to eight HubDevices each and bind selection to the room id. The hub owns no data: onToggle and onHold hand you the device and you change your model.HubDevice.tint indexes the palette you pass in DeviceHubStyle, so the same device keeps its colour in every preset.material to 0 for flat discs.HubDock and HubDotMatrix are separate so you can put destinations, a voice button or anything else on the capsule. The matrix animates only while isListening is true and holds still under Reduce Motion.DeviceHubExample at the end of DeviceHub.swift is the screen shown in the preview, with loading and hub-offline states and a small command matcher behind the keyboard and voice. Replace run(_:) with your assistant.Pieces that work well next to this one.