Maintainer: Tony Di Bona | Updated: May 2, 2026
Using Raspberry Pi Imager, select Raspberry Pi OS 64-bit (2026-04-21). Click the settings gear and configure:
sudo apt update && sudo apt upgrade -y
sudo visudo
Find this line: %sudo ALL=(ALL:ALL) ALL
Change it to:
%sudo ALL=(ALL:ALL) NOPASSWD: ALL
curl -sL https://deb.nodesource.com/setup_24.x | sudo bash -
sudo apt install -y nodejs
cd ~
git clone https://github.com/MagicMirrorOrg/MagicMirror
cd MagicMirror
npm run install-mm
cp ~/MagicMirror/config/config.js.sample ~/MagicMirror/config/config.js
mkdir -p ~/.config/autostart
vi ~/.config/autostart/magicmirror.desktop
Add this content:
[Desktop Entry]
Type=Application
Name=MagicMirror
Exec=bash -c 'cd /home/pindari/MagicMirror && WAYLAND_DISPLAY=wayland-0 npm start'
X-GNOME-Autostart-enabled=true
vi ~/.config/autostart/randr.desktop
Add this content:
[Desktop Entry]
Type=Application
Name=Display Rotation
Exec=bash -c 'WAYLAND_DISPLAY=wayland-0 wlr-randr --output HDMI-A-1 --transform 90 >> /tmp/randr.log 2>&1'
X-GNOME-Autostart-enabled=true
The Raspberry Pi 4 may not correctly read the monitor's EDID data and fall back to a lower resolution. To force 1920x1080:
sudo vi /boot/firmware/cmdline.txt
Add video=HDMI-A-1:1920x1080@60 to the end of the existing single line, separated by a space. The file must remain a single line.
sudo reboot
Verify the display resolution and rotation:
WAYLAND_DISPLAY=wayland-0 wlr-randr
Confirm that the output shows 1920x1080 px as the current mode and Transform: 90.
Verify Node.js and MagicMirror status:
node -v && npm -v
ps aux | grep electron | grep -v grep
cd ~/MagicMirror/modules
git clone https://github.com/AdamMoses-GitHub/MMM-ImageSlideshow.git
The photos folder already exists as exampleImages inside the module. Upload photos to:
~/MagicMirror/modules/MMM-ImageSlideshow/exampleImages/
Photos should be 1040 x 614 pixels and in 16:9 aspect ratio for best results.
cd ~/MagicMirror/modules
git clone https://github.com/ZachR19/MMM-Todoist2.git
cd MMM-Todoist2
npm install
vi ~/MagicMirror/config/config.js
Replace the entire file with:
let config = {
address: "localhost",
port: 8080,
basePath: "/",
ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"],
useHttps: false,
httpsPrivateKey: "",
httpsCertificate: "",
language: "en",
locale: "en-US",
logLevel: ["INFO", "LOG", "WARN", "ERROR"],
timeFormat: 24,
units: "metric",
modules: [
{
module: "clock",
position: "top_left",
header: "Local Time",
config: {
timezone: "Pacific/Auckland",
timeFormat: 12,
showPeriod: true,
showDate: true,
dateFormat: "ddd, MMM D, YYYY",
displaySeconds: false,
}
},
{
module: "clock",
position: "top_right",
header: "California Time",
config: {
timezone: "America/Los_Angeles",
timeFormat: 12,
showPeriod: true,
showDate: true,
dateFormat: "ddd, MMM D, YYYY",
displaySeconds: false,
}
},
{
module: "MMM-ImageSlideshow",
position: "upper_third",
config: {
imagePaths: ["modules/MMM-ImageSlideshow/exampleImages/"],
slideshowSpeed: 5000,
randomizeImageOrder: true,
fixedImageWidth: 1040,
fixedImageHeight: 614,
}
},
{
module: "weather",
position: "middle_center",
config: {
weatherProvider: "openmeteo",
type: "forecast",
lat: -41.2190,
lon: 175.4601,
maxNumberOfDays: 7,
units: "metric",
showPrecipitationAmount: true,
showPrecipitationProbability: true,
showWindDirection: true,
roundTemp: true,
colored: true,
appendLocationNameToHeader: false,
}
},
{
module: "calendar",
position: "bottom_left",
header: "Upcoming Events",
config: {
maximumEntries: 10,
maximumNumberOfDays: 30,
showLocation: false,
fade: false,
timeFormat: "dateheaders",
appendLocationNameToHeader: false,
calendars: [
{
url: "YOUR_GOOGLE_ICAL_URL",
symbol: "calendar-days",
}
],
}
},
{
module: "MMM-Todoist2",
position: "bottom_right",
header: "Tasks",
config: {
accessToken: "YOUR_TODOIST_API_TOKEN",
maximumEntries: 60,
updateInterval: 10*60*1000,
fade: false,
showProject: false,
sortOrder: ["priority"],
projects: ["YOUR_PROJECT_ID"],
}
},
],
};
if (typeof module !== "undefined") { module.exports = config; }
vi ~/MagicMirror/config/custom.css
Add this content:
:root {
--gap-body-left: 20px;
--gap-body-right: 20px;
}
.clock .module-header {
font-size: 1.65em;
}
.clock .date {
font-size: 2.55em;
}
.clock .time {
font-size: 4.65em;
}
.weather .forecast .day {
font-size: 2em;
}
.weather table {
font-size: 2em;
}
.region.upper.third {
top: calc(33% - 60px);
}
.region.middle.center {
top: calc(65% - 120px);
}
.region.bottom.left {
max-height: 600px;
overflow: hidden;
}
.region.bottom.right {
max-height: 600px;
overflow: hidden;
}
.calendar .module-header {
font-size: 2em;
}
.calendar .title {
font-size: 1.5em;
}
.calendar .time {
font-size: 1.5em;
}
.calendar .symbol {
font-size: 1em;
}
.calendar .dateheader {
font-size: 1.5em;
}
.MMM-Todoist2 .module-header {
font-size: 2em;
}
.MMM-Todoist2 .title {
font-size: 1.5em;
}
.MMM-Todoist2 .dueDate {
font-size: 1.5em;
}
.MMM-Todoist2 .projectname {
font-size: 1.5em;
}
vi ~/MagicMirror/config/config.js
sudo reboot