Building a smart mirror is the ultimate intersection of woodworking, hardware integration, and embedded Linux. While the core MagicMirror² software handles the beautiful UI, the underlying hardware dictates whether your mirror is a responsive dashboard or a laggy, screen-burned paperweight. For a 2026 build, the Raspberry Pi 5 (4GB) running Raspberry Pi OS Bookworm 64-bit is the definitive sweet spot, offering enough headroom to run Electron, local facial recognition, and heavy API polling without choking.
This guide skips the basic 'how to install npm' fluff. We are going straight into wiring a hardware PIR motion sensor to wake the display, writing a robust Bookworm-compatible Python wake script, and debugging the exact Electron crash errors that stall 90% of first-time builds.
Spec Sheet & Parts List
Do not under-power your Pi 5. The MagicMirror Electron wrapper is notoriously memory- and power-hungry during boot. Use the exact variants listed below to avoid brownout warnings and USB disconnects.
| Component | Exact Variant / Model | Est. Price | Build Notes |
|---|---|---|---|
| Compute Board | Raspberry Pi 5 (4GB RAM) | $60 | 8GB is overkill unless running local LLMs or heavy ML face recognition. |
| Power Supply | Official 27W USB-C PD PSU | $12 | Mandatory for Pi 5. Third-party 5V/3A supplies will throttle the CPU. |
| Motion Sensor | HC-SR501 PIR Module | $3 | Adjust the onboard potentiometers to 3s delay and low sensitivity. |
| Display Panel | 24-inch 1080p IPS (e.g., Dell P2425H) | $130 | IPS is required for viewing angles. Remove the plastic bezel for the mirror frame. |
| Mirror Glass | Two-way acrylic (1/8 inch) | $45 | Acrylic is lighter and safer than glass for wall mounting. |
Hardware Assembly & GPIO Pin Mapping
To prevent LCD burn-in and save power, the mirror should only be illuminated when someone is standing in front of it. We use the HC-SR501 PIR sensor to trigger the Pi's display power state via GPIO.
PIR to Raspberry Pi Pin Mapping
| HC-SR501 Pin | Raspberry Pi 5 Pin | GPIO / Function | Wire Color (Typical) |
|---|---|---|---|
| VCC | Pin 2 | 5V Power | Red |
| GND | Pin 6 | Ground | Black |
| OUT | Pin 11 | GPIO 17 | Yellow |
The Motion-Wake Python Script (Bookworm Compatible)
Raspberry Pi OS Bookworm shifted the default display server from X11 to Wayland. Old tutorials telling you to use xset dpms force off will fail silently. The correct, compositor-agnostic method is to use the vcgencmd utility provided by the Raspberry Pi firmware.
This script targets the Raspberry Pi 4 and 5 on Bookworm 64-bit. It uses the gpiozero library for reliable edge-detection on the PIR pin.
#!/usr/bin/env python3
import time
import subprocess
import logging
from gpiozero import MotionSensor
from threading import Timer
# Target: Raspberry Pi 4 / 5 (Bookworm 64-bit)
PIR_PIN = 17
TIMEOUT_SECONDS = 120
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s')
pir = MotionSensor(PIR_PIN, queue_len=5, threshold=0.6)
def toggle_display(state):
# state: 0 = off, 1 = on
cmd = f'vcgencmd display_power {state}'
try:
subprocess.run(cmd, shell=True, check=True, capture_output=True, text=True)
logging.info(f'Display powered {"ON" if state else "OFF"}')
except subprocess.CalledProcessError as e:
logging.error(f'Failed to toggle display: {e.stderr}')
class ScreenSaver:
def __init__(self, timeout):
self.timeout = timeout
self.timer = None
self.is_awake = False
def wake(self):
if not self.is_awake:
toggle_display(1)
self.is_awake = True
self.reset_timer()
def sleep(self):
toggle_display(0)
self.is_awake = False
def reset_timer(self):
if self.timer:
self.timer.cancel()
self.timer = Timer(self.timeout, self.sleep)
self.timer.start()
if __name__ == '__main__':
saver = ScreenSaver(TIMEOUT_SECONDS)
logging.info('MagicMirror PIR Wake Service Started...')
try:
# Initial state
saver.wake()
# Bind events
pir.when_motion = saver.wake
# Keep script alive
while True:
time.sleep(1)
except KeyboardInterrupt:
logging.info('Shutting down PIR service.')
if saver.timer:
saver.timer.cancel()
toggle_display(1) # Leave screen on upon exit for debugging
Save this as /home/pi/mirror_wake.py and create a systemd service to run it on boot. This ensures your mirror sleeps automatically if you leave the house.
Debugging: Fixing Electron & Boot Errors
If your mirror boots to a black screen or dumps you back to the terminal, you have likely hit an Electron or Node.js dependency failure.
The Exact Error String
The most common failure during npm install on ARM64 boards is:
npm ERR! code 1
npm ERR! path /home/pi/MagicMirror/node_modules/electron
npm ERR! command failed
npm ERR! command sh -c node install.js
First Three Things to Check When It Fails
- Node.js Version Mismatch: MagicMirror² currently requires Node.js 20.x or higher. If you are running Node 16 or 18 from an old tutorial, Electron will fail to compile its ARM64 binaries. Purge your current Node and install the 20.x LTS via NodeSource.
- Architecture Confusion (armhf vs arm64): If you flashed the 32-bit Raspberry Pi OS but are trying to install 64-bit Electron modules, the
install.jsscript will crash. Verify your OS withuname -m(it should sayaarch64). - Network Timeouts: The Electron binary is ~90MB. On a weak WiFi signal, the download times out silently, leaving a corrupted
distfolder.
Ranked Causes & Fixes
| Cause | Fix / Command |
|---|---|
| Corrupted Electron Cache | Run rm -rf node_modules/electron/dist then npm run install-mm in the MagicMirror root. |
| Missing Build Tools | Run sudo apt install build-essential python3-dev to satisfy node-gyp requirements for native modules. |
| Server.js Boot Delay | If you see ERR_CONNECTION_REFUSED in the Electron logs, your server is booting slower than the UI. Increase the electronOptions.webPreferences.nodeIntegration delay in config.js. |
Extending and Simplifying Your Build
Once the core is stable, you have two paths: adding complexity or abstracting it away.
How to Extend:
Add the MMM-Remote-Control module to edit your config.js from your smartphone. For multi-user households, integrate MMM-Face-Reco using a Raspberry Pi Camera Module 3. This module uses OpenCV to detect faces and swap the UI layout based on who is standing in front of the mirror. Note that face recognition will push the Pi 5's CPU usage to ~40%, so ensure your enclosure has passive cooling heatsinks on the SoC.
How to Simplify:
If fighting with npm, Wayland, and systemd services sounds miserable, skip the manual Linux setup entirely. Flash MagicMirror OS (a pre-configured BalenaOS image) directly to your microSD card using the Raspberry Pi Imager. It handles the Electron wrapper, display sleep, and OTA updates via a web dashboard, reducing your setup time from 4 hours to 15 minutes.
MagicMirror Raspberry Pi FAQ
Can I run a MagicMirror Raspberry Pi on a Pi Zero 2 W?
Yes, but with severe limitations. The Pi Zero 2 W has only 512MB of RAM. The Electron wrapper alone consumes ~350MB. If you add more than two lightweight modules (like a basic clock and weather), the system will swap to the microSD card, causing massive lag and card corruption. To use a Zero 2 W, you must run MagicMirror in 'server-only' mode and use a lightweight kiosk browser like Midori instead of Electron.
Why is my MagicMirror Raspberry Pi screen burning in?
Static white text (like the default clock and calendar borders) left on an LCD or OLED panel for weeks will cause permanent image retention. You must implement the PIR motion-wake script provided above to physically cut power to the display backlight when the room is empty. Additionally, enable the built-in screen-saver module in your config.js to shift pixels slightly during idle times.
How do I update MagicMirror modules without breaking the core?
Never run npm update in the root /home/pi/MagicMirror directory; this will overwrite core dependencies and likely break the Electron wrapper. To update a specific third-party module, navigate into its folder (e.g., cd modules/MMM-Weather), run git pull, and then run npm install only if the module's documentation explicitly states that dependencies have changed.
Does the MagicMirror Raspberry Pi work on Raspberry Pi OS Bookworm 64-bit?
Yes, Bookworm 64-bit is the recommended OS for the Pi 5. However, because Bookworm defaults to the Wayland display server instead of X11, older modules that rely on X11 window management (like forced fullscreen or screen rotation scripts) will fail. You must use Wayland-compatible commands like wlr-randr or the firmware-level vcgencmd for display manipulation.






