MagicMirror

Back in 2014, a Raspberry Pi enthusiast by the name of Michael Teeuw shared his build of a “magic mirror” with the world in a six-part series. The system consisted of a Raspberry Pi and monitor running a web browser in kiosk mode, with a web server that provided a dashboard interface — all stored in a custom-built case with a one-way mirror. Since his post, others around the world have built these devices for their home (including myself), forming both a community and an interesting open-source project. The recent release of MagicMirror2 (MM2) version 2.12.0 gives us an opportunity to learn more about where the project started and where it is today.

The MM2 project provides the software to convert what would otherwise be a normal household mirror into a valuable source of information. This information could take the form of drive times, train schedules, daily news, server loads, sports scores, or even the feed from the doorbell when someone is at the door. With the right know-how, the surface can even become interactive through the use of hand gestures or as a touchscreen.

During the first two years after Teeuw’s posts, the GitHub repository for the project had been forked over 500 times. By October 2016, The MagPi (the official Raspberry Pi Foundation magazine) had declared Teeuw’s project a first place winner in its “50 Greatest Raspberry Pi Projects” [PDF] issue.

In December 2016, Teeuw announced MagicMirror2 under the MIT license. MM2 was designed to replace the original code base; in the announcement, Teeuw explained why:

In the past two years, many community members worked on expanding the MagicMirror system allowing them to customize it to their needs. And while I admire this effort, I felt it needed some rethinking in order to grow beyond what was possible with the current version.

In another post Teeuw stated that MM2 was funded by a {“}successful entrepreneur{“}, who contracted him to build a custom mirror as the centerpiece of their new home’s living room.

MM2 is built using Electron and operates on a web server and browser model. The project can be divided broadly into two segments: the core framework and the modules. The core framework provides WebSocket communication between the browser-based user interface (UI) and the backend services; this framework is then used by modules to provide the functionality of the UI. MM2 ships with a handful of default modules; hundreds of third-party modules written by contributors are also available. The core MM2 project has 243 contributors to date; the most recent was in July 2020. The latest release fixed a number of bugs, added the ability to configure MM2’s log verbosity, and cleaned up several places in the code to make the project easier to maintain.

Since Electron is cross-platform, in theory MM2 can be run in most common environments. However, the project itself exclusively supports Raspberry Pi devices (excluding the Zero series). The installation documentation provides multiple different options for getting started, including cloning the repository, using a Docker image, or using a pre-configured Raspberry Pi OS (formerly Raspbian) image.

Building the interface for MM2 is straightforward for many (if not most) configurations. Some modules are more complicated than others, especially ones that interact with hardware or communicate with each other; more fiddling might be required in those circumstances. Everything is controlled by a JavaScript configuration file. Here is a screenshot of the MM2 interface, taken from a mirror I built for my home (rendered in a web browser):

My MM2 Interface
My MM2 Interface

This interface is implemented with five MM2 modules: a community-contributed MQTT client for the dinner menu, along with the built-in clock, current weather, weather forecast, and news-feed modules. Each component has its own configuration in addition to the MM2 core options that are always available. Modules are defined in the modules section of the global MM2 configuration as an array of JSON objects.

Modules that provide a visual aspect can be positioned in the UI using the position option. There are a total of 13 positions that MM2 divides the UI into. For example, bottom_bar places the headlines centered at the bottom of the screen as shown in the screenshot. Multiple modules can be placed in the same position and are rendered in the same order they are provided within the configuration.

The MM2 module framework provides each module with the ability to listen for and respond to notifications from other modules. For example, the newsfeed module has several notifications it listens for that can be used to control the feed in the interface (such as moving to the next article headline). This allows interaction with other modules like the community-contributed MMM-Gestures, which provides a mechanism to interface MM2 with infrared sensors that let the user “wave” their hand in front of the mirror to interact with it. Another module that I have personally found useful is MMM-homeassistant-sensors, which enables me to pull data from my Home Assistant hub into the MM2 UI.

For users like myself, who would like to provide their dashboard display in multiple locations and across multiple devices, MM2 provides a convenient way to manage that configuration. I run one instance of MM2 in server-only mode, with two Raspberry-Pi-powered displays that connect to it in client-only mode. This allows me to manage a single configuration and provide a consistent interface across both devices.

One place MM2 doesn’t provide much as a project is around security, offering no vulnerability disclosure policy or security-focused documentation. A review of the project issue tracker did not turn up any reported security issues. It did show that the contributors keep the various dependencies used by the project up to date (including security fixes), indicating at least an interest in security concerns. It is worth noting that running MM2 behind a NAT firewall is likely a good idea, with proper care being taken to secure the underlying OS of the Raspberry Pi. For security within the LAN, MM2 allows users to configure lists of IP addresses that are authorized to access the server. It is also important to keep in mind that, since the majority of functionality comes from third-party modules not vetted by the project, care should be taken to ensure that those modules are safe before using them.

To get involved with the MM2 community, the first stop would be the project forums or perhaps the Discord channel. For contributors, the project also outlines the best ways to get involved. Alternatively, if the goal is to add new functionality in the form of a module, the module development documentation should have everything needed to do so. In my home, the MM2 devices have become an important daily part of life. Any readers interested in having a low-cost “magic mirror” of their own are encouraged to take a look at the project.