# MMM-Remote-Control puts a browser between you and your smart mirror

> MMM-Remote-Control is a MagicMirror2 module that shuts the mirror down, hides and shows modules and exposes a REST API for anything that can open a URL. It assumes you run the mirror yourself on a Raspberry Pi and control it from your own network.

**Jopyth/MMM-Remote-Control** — Magic Mirror Module to shutdown or configure your mirror

- Repository: https://github.com/Jopyth/MMM-Remote-Control
- Stars: 603 · Forks: 154
- Language: JavaScript
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/jopyth-mmm-remote-control

## Shut down, hide, show, all from a browser

MMM-Remote-Control is a module for MagicMirror2 that lets you use a browser to shut down your mirror, hide and show modules, and do other things with it. The motivation stated in the project is practical rather than decorative. A Raspberry Pi running a mirror tends to live on an SD card, and pulling the power while it runs is what wears that card out, so the project argues for a proper shutdown every time. If that shutdown is one tap on a phone instead of a walk to the kitchen, the argument lands. The interface is a separate web page rather than an overlay on the mirror itself, and the project says it should work on a desktop, a smartphone or a tablet. Underneath the interface there is a RESTful API for controlling the mirror from other network enabled devices or controllers, which the project describes as anything that can open a URL.

## Installing means cloning into the modules directory

There is no package to publish and no wizard. The module is installed the way MagicMirror2 modules usually are, by cloning the repository into the modules directory and installing its dependencies without the development packages.

```bash
cd ~/MagicMirror/modules
git clone https://github.com/Jopyth/MMM-Remote-Control
cd MMM-Remote-Control
npm ci --omit=dev
```

The installation displays a sample API key that you can use, and the key is optional. One note in the project documentation covers a detail that will otherwise puzzle you: an npm allow-scripts warning for @scarf/scarf arrives during the install through swagger-ui-dist, and the documentation says this is upstream and harmless for the runtime, so it can be ignored or approved with npm approve-scripts @scarf/scarf for cleaner output.

## The config entry decides what the web interface exposes

The module is added to the modules array in your config.js, and a position is set so the mirror can display the URL and the QR code, which you can then hide using the remote control itself. The configuration entry carries a set of switches, most of them commented out by default.

```js
    {
      module: "MMM-Remote-Control",
      position: "bottom_left",
      config: {
        customCommand: {}, // Optional, see "Using Custom Commands" below
        secureEndpoints: true, // Optional, see API/README.md
        // customMenu: "custom_menu.json", // See "Custom Menu Items" below
        // apiKey: "", // See API/README.md for details
        // classes: {}, // See "Custom Classes" below
        // showModuleApiMenu: false, // Disable the Module Controls menu
        // showQRCode: true, // Display a QR code for mobile access (default: true)
        // qrCodeSize: 150, // QR code size in pixels (default: 150)
        // qrCodePosition: "above" // "below", "above" (default), or "replace"
      }
    },
```

The menu entries can be trimmed with showModuleApiMenu and showNotificationMenu, and the QR code can be resized or repositioned, including a replace mode that swaps the QR code for the URL. The customMenu option points at a JSON file for extra menu items, with a sample in the repository, and customCommand is where you register shell commands the mirror is allowed to run. secureEndpoints and apiKey are the security relevant pair, and the project points at its API documentation for the details of both.

## Reaching the mirror from a phone takes an address and a whitelist

The single most important configuration step is not in the module at all. MagicMirror2, and therefore the remote control, is not reachable externally by default, so the project tells you to set address and ipWhitelist in your config.js if you want to open the interface from another device. The example opens the server on every interface and allows two named machines.

```js
address: "0.0.0.0",
port: 8080,
ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:192.168.0.42", "::ffff:192.168.0.50"],
```

A whole range can be allowed instead of individual devices, which the project shows for a local subnet.

```js
ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:192.168.0.0/120", "192.168.0.0/24"],
```

The interface itself is then a single page on the mirror's port, at the /remote.html path. The whitelist entries appear in both plain and IPv4 mapped IPv6 form, because a client connecting over a dual stack socket arrives as ::ffff: followed by the address. Note what this configuration does not include: no port forwarding to the internet, no tunnel, and no authentication by default. The mirror stays inside your own network, which is the security model, and it also means the module is unusable if your phone is on a different network than the mirror.

## A REST API is the real interface under the buttons

The web page is a front end, and the project points at a separate API document for the underlying endpoints. The useful part for other software is that any method offered in the user interface can also be called with a GET request or through a module notification, and the project names MMM-ModuleScheduler as an example of a module that triggers those calls on a schedule. That means the module is not only a phone page. It is a small HTTP surface that another module, a home automation rule or a shell script can call. The API key and secureEndpoints settings exist for that surface, which is where the access control question has to be answered.

## A QR code on the mirror and a PWA on the phone

Two recent additions target the phone specifically. The mirror can display a QR code that a phone camera reads to reach the remote interface immediately, and the remote interface can be installed as a progressive web app, with the project describing the result as working like a native app with offline support. The installation steps differ per platform: on Android with Chrome you use the menu and choose Install app or Add to Home screen, and on iOS with Safari you use the share sheet and Add to Home Screen. The project also flags a limitation here, that PWA installation may require HTTPS and might only work when MagicMirror2 runs under HTTPS, and it asks for feedback on that.

## Versions are git tags, and module order breaks hidden state

There are no GitHub releases for this project, so version management is done with git directly. Updating is a pull followed by a dependency install, and older versions are reachable by tag.

```bash
cd ~/MagicMirror/modules/MMM-Remote-Control
git pull
npm ci --omit=dev
```

To see which versions exist, the project asks you to fetch the tags and list them.

```bash
cd MagicMirror/modules/MMM-Remote-Control # or wherever you installed the Mirror and the module
git fetch # fetch all tags
git tag # display them
```

A specific version is then checked out with git switch --detach v1.0.0, and git switch master returns to the most recent version. The one behaviour worth planning around is documented under known limitations. Whenever the order of modules in config.js changes, or modules are added or removed, the module indices change, so the hidden and shown state may not be applied correctly. The fix is to reconfigure and save the configuration again. In practice, a config.js edit is the moment to expect the mirror's visibility state to reset.

## MIT licensed, version 6.1.0, released with a changelog tool

The module is MIT licensed and the package version is 6.1.0, with the author listed as Joseph Bethge. The repository carries a CHANGELOG.md and a changelog.config.js, and the release script runs commit-and-tag-version, so tags and the changelog are produced from commit messages rather than uploaded by hand. The test setup is worth noting for anyone planning to modify the module, because it is broader than a single test runner: the test script chains a lint pass using eslint and prettier, a spelling check through cspell, and then the node test runner over the test files, with separate scripts for unit, integration, DOM and coverage runs using c8. The last push was on 2026-10-19, so the module is still being worked on, and the automated test workflow in the repository runs against the master branch.

## Conclusion

MMM-Remote-Control suits someone who runs MagicMirror2 on a Raspberry Pi at home or in a small office and wants a phone shortcut for shutting it down cleanly, hiding modules and triggering actions. It does not suit a setup where the mirror has to be reachable from the internet, because the module inherits the platform's local network posture and its access control is an IP whitelist. Before enabling it, set address and ipWhitelist in your config.js, decide whether secureEndpoints and an apiKey are needed, and remember that reordering modules in config.js resets which modules are hidden until you save the configuration again.

## FAQ

### How do I install MMM-Remote-Control on a MagicMirror2 install?

Clone the repository into your modules directory and install the runtime dependencies with npm ci --omit=dev. The install prints a sample API key that you can use, and it is optional.

### How do I reach the remote control from my phone?

Set address and ipWhitelist in your config.js, because MagicMirror2 is not reachable externally by default. The module can then show a QR code on the mirror, and the remote page lives at the /remote.html path on the mirror's port.

### Can other software control a MagicMirror2 through MMM-Remote-Control?

Yes. The module includes a RESTful API, and any method offered in the interface can be called with a GET request or through a module notification. The project names MMM-ModuleScheduler as an example of calling those methods on a schedule.

### What happens to hidden modules after I reorder config.js?

Changing the order of modules in config.js, or adding and removing modules, changes the module indices, so the hidden and shown state may not apply correctly. The documented fix is to reconfigure and save the configuration again.

## Sources

- [Issues](https://github.com/Jopyth/MMM-Remote-Control/issues)
- [Jopyth/MMM-Remote-Control on GitHub](https://github.com/Jopyth/MMM-Remote-Control)
- [License: MIT](https://github.com/Jopyth/MMM-Remote-Control/blob/master/LICENSE)
- [README](https://github.com/Jopyth/MMM-Remote-Control/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/jopyth-mmm-remote-control
