Magic Frame — self-hosted dashboard for family boards, wall monitors and picture frames with deep HA integration (v1.0 released)

Hey everyone,

I'm launching Magic Frame v1.0, an open-source self-hosted dashboard for the displays in your home — wall-mounted monitors, kitchen panels, picture frames, old TVs. It treats Home Assistant as a first-class citizen, not as an afterthought, and the same display can switch between smart-home dashboard mode and a real picture frame fed by your Immich albums.

Why I built it

We have a portrait monitor mounted on the wall in the kitchen as our family board (shopping list, calendar, weather, who needs to feed the cat). I wanted two things baked into one display:

  1. Real HA integration — not iframe hacks, not screenshots, but actual live entities and direct service calls. The HA frontend works great in a browser, but it doesn't feel right as a family board sitting on the wall all day.
  2. A real home for my Immich photos — I have ~30k photos sitting on my self-hosted Immich, and the only ways to display them on a screen at home all involved either piping them through someone else's cloud (DAKboard etc.) or running a separate slideshow app with no overlays.

Magic Frame combines both. Same display does smart-home dashboard during family hours and rotates through your Immich album as a real picture frame the rest of the time.

Home Assistant integration

What I felt was always half-baked in other dashboards:

  • Live entity updates via WebSocket (no polling)
  • Buttons that call HA services and webhooks directly — tap = service call
  • Notification tiles with rule-based auto-show / auto-hide. Example: light.washing_machine turns on → tile "Washing machine done" pops up, tap to dismiss → tile hides until rule fires again. Same pattern for "feed the cat", dryer done, motion alerts
  • Shopping & Todo widgets that read & write todo.* entities — what you tick off on the wall is gone from HA too, and vice versa
  • Color & icon rules per entity state — door sensor green/closed, red/open; lights show actual brightness as a tile gradient
  • Multi-instance support if you run several HAs

Picture-frame mode (Immich + WebDAV)

The same display can fade all HA entities away and just rotate wallpapers — tap a toggle button → dashboard is back. The photo source is the interesting part for self-hosters:

  • Direct connection to your Immich instance — drop in the Immich URL + an API key in Settings → Integrations, photos never leave your home network, no cloud relay, no third-party account
  • Per-view album picking — the kitchen monitor rotates "Family", the bedroom tablet shows "Travel", the living-room TV cycles "Landscape Photography". Each view binds to its own Immich album
  • Auto-pickup of new photos — add a photo to the album in Immich today, it shows up on the displays automatically
  • WebDAV folder support too — works with Nextcloud, Seafile, or any plain WebDAV source
  • Smooth crossfade transitions, configurable rotation interval

So the same tablet that shows "Washing machine done" notifications at 9pm becomes a picture frame with last summer's vacation photos at 3am. No re-config, just a toggle.

Editor & layouts

  • Drag-&-drop editor on a 24-column grid — no YAML, no CSS tweaking
  • Multiple views, each with its own URL — portrait for the kitchen monitor, landscape for the living-room TV, picture-frame style for the side-table tablet
  • Live sync via WebSocket — change a widget on your laptop, every connected display updates instantly
  • Auto-snapshot before every save (last 20 kept) + manual export/import

10 core widgets

Clock · Weather (Open-Meteo / DWD / OpenWeatherMap / HA entity) · Calendar (iCal + Google + MS365 OAuth) · HA-Entities · HA-Notifications · Buttons · Timer · Quick-Post via REST/iOS Shortcut · Shopping · Todos

Custom widgets

Upload a JS bundle through the UI — hot-loaded, no container restart. Manifest defines fields (text/number/boolean/color/url). Example module included in the repo.

Optional hosting layer

For when you want to reach it from outside: Caddy reverse proxy + auto-HTTPS via Let's Encrypt · 10 DNS providers built in for ACME DNS-01 · DDNS updater (Cloudflare/Hetzner/DynDNS-v2) · 2FA TOTP + recovery codes · in-app brute-force protection. All off by default — pure LAN works out of the box.

Install

Docker Compose stack (Next.js 15 + Postgres 16 + Caddy 2). Two commands on any Linux box (Pi 4/5, NAS, NUC, old laptop):

curl -fsSL https://get.docker.com | sh
curl -fsSL https://raw.githubusercontent.com/jeremiaa/magic-frame/main/deploy/install.sh | bash

Then http://<server-ip>/login → admin setup → Integrations → drop in your HA URL + Long-Lived Access Token (and Immich URL + API key if you want photo wallpapers) → entities show up.

Repo + Docs

GitHub: GitHub - jeremiaa/magic-frame: Local glassmorphism dashboard for tablets, monitors, and digital picture frames. Drag-&-drop editor, live sync, Home Assistant, custom modules. Self-hosted, no cloud account required. · GitHub

Full README has more screenshots, a demo video, custom-module dev docs, a Troubleshooting section, and the iOS-Shortcut/REST-API reference for the companion endpoints.

What I'd love to hear

This is v1.0 and I'm just getting started. Especially curious:

  • What HA-specific widgets or behaviors are still missing for you in dashboards like this?
  • For people running family boards or wall displays — what's annoying in your current setup?
  • For Immich users — would "tablet as a real picture frame fed by Immich albums" be useful for you, or do you already have a setup you like?
  • Any feedback on the install / first-run flow?

Honest disclosure: I'm new to OSS — this is my first real project. I built it pair-programming with Claude as a coding assistant. Architecture, features and UX decisions are mine; implementation is AI-generated and reviewed by me. License is Polyform Noncommercial — free for personal/household/club/NGO/school use.

11 Likes

Ok, i bit the bullet. Very impressive.

A lot of the gui in german, even with English set.

No camera view, so cannot keep an eye on the horses.

Auto complete entity names

oh nice, thanks for giving it a shot!

yeah translations have gaps - english dict isn't complete yet. will do a
sweep through it.

entity autocomplete - good point, the HA connection is already there
so should be doable.

camera widget i didn't think of, but makes sense for a wall display.
will see what the HA camera proxy can do.

all three on github now

1 Like

small update - v1.0.2 just shipped

translations - did a full sweep through the english dict, and made
english the default. should be 100% covered now.

entity autocomplete - works in every HA widget inspector, fuzzy match
on entity_id + friendly_name, arrow keys to pick.

icon picker - filters by mdi when you're in HA inspectors so you
don't get drowned in solar:* / hugeicons:* variants.

camera widget i'm still working on

heads-up for anyone else who installed in the last few days - i did
some history rewrites in launch week which can make git pull fail
with "divergent branches" or "would clobber tag v1.0.0". one-time fix:

git fetch --force --tags origin && git reset --hard origin/main

then ./deploy/install.sh works as normal. install script handles
this case automatically from v1.0.2 on. sorry for the noise.

release notes: Release v1.0.2 — UX polish + first community feedback round · jeremiaa/magic-frame · GitHub

1 Like

Is it possible to change views, eg by swiping?

1 Like

not possible yet, but cool idea :slight_smile: on the list for v1.1.

today a button widget can already show/hide multiple other widgets at once, but no stacking at the same grid position — so you can toggle a group on/off, not swap layouts. stacking + HA-entity triggers (currently only manual button) both on the roadmap.

small update :slight_smile: - v1.0.5 is out with a few fixes:

  • widget titles now translate properly - they were stuck in german on english setups (thanks for flagging that)
  • show/hide buttons were silently breaking on freshly created and duplicated views - fixed
  • you can now hide individual slots in the button widget if you only want one or two
  • from the last couple versions too: smoother wallpaper transitions on samsung/tizen browsers, 12h/24h + date format toggle and a timezone picker on the clock, en-US defaults on english

update with:

cd ~/magic-frame && git pull && docker compose up -d --build

Looks great! Can't wait to spin it up!

1 Like

This looks great! Currently we're running a RPI 4 with a touch screen usb monitor.

A couple of things we've liked you might consider.

Option to just shut the display off for some hours. Maybe no one is awake to see photos at 3am

Watchdog services. Reboot (with cool down to avoid boot loops) if you lose Wi-Fi. Switch back to main view after a time out. For us we like default to be calendar, but kids will often switch to weather or their core board and not switch back.

I'm curious what hardware you're running? The largest touch screen monitor I could find was like 14". I love the look of your large portrait one. Is that touch screen?

1 Like

@shaun-adam thanks :slight_smile:

quick clarification on how it runs, because it changes a few of your points: magic frame is client-server, not a single-device app. one machine runs the server (backend + db in docker), and each display is just a browser pointing at a view URL. the displays stay "dumb" — they only load a page.

so it works two ways:

  • central server for the whole home, multiple displays each on their own view URL
  • or all-in-one on a single box — a pi4 can run the server AND open a local browser kiosk pointing at localhost/view/. same binary, you just decide. (haven't written that guide up yet, want to test it properly first)

on your specific points — most of them live at the display layer, not in the app:

  • display off at night: that's the screen's job. mine's a 27" samsung smart monitor M5 (no touch, built-in tizen browser) and HA turns it on/off on a schedule natively. for dumb monitors i use TouchKIO on a pi (HA integration, controls screen power). the photo-frame is an old tablet on Fully Kiosk.
  • wifi watchdog / reboot: same layer — TouchKIO or Fully Kiosk handle that, the app doesn't need to.

the one that IS an app feature is your "kids switch to weather and don't switch back". like i mentioned earlier in the thread, today a button widget can already show/hide multiple other widgets at once — so you can toggle a group on/off already, just no stacking at the same grid spot yet (so no full layout-swap). what's coming:

  • multiple linked views you can swipe/switch between
  • the concrete plan for HA control is show/hide widgets driven by HA entity state (tracked as #6) — so a view rearranges itself based on what's happening in the house, not just a manual tap
  • and i'm thinking about a custom HA integration on top of that, so you could switch the whole active view straight from an automation (presence, time of day, etc.) — not locked in yet, still chewing on it

so "default to calendar, return after a timeout" becomes a real rule rather than a kiosk hack.

re hardware: like above, the 27" M5 — no touch, touch only matters for the buttons, everything else is glanceable.

1 Like

@webash thanks :folded_hands: hope you like it once it's running, let me know if anything's unclear

Hi, thank you for all of your work on this. It's a great product. I've been trying to think of the best way to display my home assistant data on the TV for a while. This is very easy to implement.

I've now deployed a screensaver on my tv that extracts various weather sensors. This replaces the standard Google slide show.

I have a few thoughts for further development. There are a few scaling and clipping issues that I've noticed. Some might be fixable but others might be browser limitations on my device.

I am finding that text inside the widget boxes needs to be scaled to match the size of the box which is fiddly to fix. It would be great if the software scaled to fit automatically (or imposed a maximum)

Also, if the state of an entity contains a lot of text this gets clipped by the display. It would be great if there was an option for it to scroll within the box or to allow multiple lines of text (the example here is my long form description of the weather forecast).

Hope that helps.

1 Like

thanks :folded_hands: glad it ran easy for you.

two things here, more design decisions than bugs:

box and text are separate — you can drag the widget box bigger/smaller in the editor however you want, the text doesn't have to follow it. the text scales off its own font-size, not the box. that's on purpose: a view i build on a 32" also has to fit on a 10" tablet, and if the text was locked to the box pixels it'd look wrong on every other size. there's a "responsive text" toggle in the inspector that's meant to auto-fit it — but honestly, just tested it again myself, it's fiddly. for now the reliable way is just keeping the text short, then it sits fine.

clipping on long text: weather + clock are non-scrolling on purpose (meant for glancing, not reading), but other widgets can scroll / go multi-line. a long forecast description fits better in one of those than the compact weather tile.

one more tip, since you usually set a screen up once and then it just stays: i sit at the editor on my laptop with the target monitor right in front of me and adjust live — with the live-sync every change shows up on the real screen instantly at its real size. saves the guessing.

but yeah you hit a sore spot, the responsive scaling isn't as smooth as it should be yet. gonna open an issue and think of something better. if you DM me a screenshot of where it clips that'd help me find the best fix.

Would love to see a docker image published for this.

2 Likes

yeah that's a good shout - right now the install builds the images locally, which works but takes a while (especially on a pi). pre-built images on ghcr would mean a pull instead of a build. it's on my list, just want to get multi-arch (amd64 + arm64) right so it works on a pi too. coming.

This is exactly what I'm looking for. I wanted to have a family board for the most important agenda items, and I wanted to display my Immich pictures. And, there you are!

I'll give it a go asap. If you need help with translation to Dutch, just let me know.

Rudi

1 Like

I gave it a spin on my W11 system, and I'm more than a little impressed! It looks great!
This installation went flawlessly; I had it working within 5 minutes. Since I'm not too eager to read any documentation, I just followed the 2 installation steps, went into the management page, configured HA, added some elements, clicked "view in new tab", and there it was. No docs needed. The interface is well designed and mostly self-explanatory.

In the next couple of days I will be playing around with it.

I suppose you want feature requests and bug reports in GitHub?
If there are questions, do you want them here in the community or in GitHub?

1 Like

ah this made my morning, thanks rudi :slight_smile: 5 min with no docs is exactly
what i was going for.

bugs and feature requests on github as issues is perfect. general
questions either works, here or github, i check both.

and dutch - id really like that. turns out the language system is
locked to german + english right now so it needs a small rebuild
before a third language actually works - just opened an issue for it
(Support more than two UI languages (i18n is hardcoded to de + en) · Issue #13 · jeremiaa/magic-frame · GitHub). once thats done ill auto
translate the dutch as a first pass and you just read over it and fix
what sounds off. ill give you a shout when its ready.

Just trying it out, and stopped at the end of the script. Port 80 already in use.
Suggestion: Script should check port 80 at the BEGINNING and suggest a different port if that one is in use already.