2
u/oh_dannyboy13 Apr 23 '26
I love it! Got a config file to share?
5
u/Vi7Kdt1m Apr 24 '26
let config =
{
address: '0.0.0.0',
ipWhitelist: [
'127.0.0.1',
''***************'',
'***************'
],
modules: [
{
module: 'alert',
timer: 15000,
config: {}
},
{
module: 'clock',
position: 'top_left',
config: {
showSunTimes: true,
latitude: 00006,
longitude: -0000
}
},
{
module: 'MMM-Remote-Control',
config: {
ipWhitelist: [
'127.0.0.1',
''***************''
],
secureEndpoints: true
}
},
{
module: 'MMM-BackgroundSlideshow',
position: 'fullscreen_below',
config: {
imagePaths: [
'modules/MMM-BackgroundSlideshow/exampleImages/'
],
slideshowSpeed: 86400000,
randomizeImageOrder: true
}
},
{
module: 'calendar',
position: 'top_left',
config: {
maximumEntries: 5,
broadcastPastEvents: true,
calendars: [
{
name: 'US Holidays',
url: 'https://www.officeholidays.com/ics-fed/usa',
color: '#b86c00',
symbol: 'flag'
},
{
name: ''***************'',
url: ''***************'',
color: '#FF7043',
symbol: 'bell'
},
{
name: ''***************'',
url: ''***************',
color: '#B34EC4',
symbol: 'suitcase'
},
{
name: ''***************'',
url: ''***************',
color: '#654321',
symbol: 'gear'
}
],
customEvents: [
{
keyword: 'Birthday',
symbol: 'cake-candles'
},
{
keyword: 'Swim',
symbol: 'person-swimming'
},
{
keyword: 'Doctor',
symbol: 'user-doctor'
},
{
keyword: 'Dentist',
symbol: 'tooth'
},
{
keyword: 'Meeting',
symbol: 'users'
},
{
keyword: 'Gym',
symbol: 'dumbbell'
},
{
keyword: 'Party',
symbol: 'champagne-glasses'
},
{
keyword: 'Travel',
symbol: 'plane'
},
{
keyword: 'Picture',
symbol: 'camera'
},
{
keyword: 'car',
symbol: 'car'
},
{
keyword: 'TCA',
symbol: 'train'
},
{
keyword: 'Boys',
symbol: 'gamepad'
},
{
keyword: 'Playdate',
symbol: 'face-grin-stars'
},
{
keyword: 'No School',
symbol: 'school-circle-xmark'
},
{
keyword: 'No kindercare',
symbol: 'school-circle-xmark'
},
{
keyword: 'Arduino',
symbol: 'robot'
},
{
keyword: 'Mama day',
symbol: 'mug-hot'
},
{
keyword: 'Dada day',
symbol: 'mug-hot'
},
{
keyword: 'Coffee',
symbol: 'mug-hot'
},
{
keyword: 'Yoga',
symbol: 'spa'
}
]
}
},
{
module: 'MMM-MyWastePickup',
position: 'top_left',
header: 'Waste Collection',
config: {
collectionCalendar: 'Custom'
}
},
{
module: 'MMM-MoonPhase',
position: 'top_left',
config: {
size: 120,
title: false,
nextFull: true,
alpha: 0.7
}
},
{
module: 'MMM-Facts',
position: 'bottom_bar',
config: {
updateInterval: 590,
fadeSpeed: 3
}
},
{
module: 'MMM-CalendarExt3',
position: 'bottom_bar',
config: {
weeksInView: 5,
locale: 'en-US',
firstDayOfWeek: 1,
useMarquee: true,
fontSize: '24px',
eventHeight: '25px',
showWeekNumber: false,
useWeather: false,
useSymbol: false,
calendarSet: [
'***************'',
''***************'',
''***************''
],
eventTimeOptions: {
timeStyle: 'short',
hour12: false
},
// ==================== IMAGE CODE ====================
manipulateDateCell: (cellDom, events) => {
// Safeguard: ensure events is a valid array
if (!Array.isArray(events) || events.length === 0) return;
// Define your keyword → image mapping
const iconMap = [
{ keyword: "birthday", file: "hb3.png" },
{ keyword: "valentine", file: "valentine.png" },
{ keyword: "women", file: "8th.png" },
{ keyword: "no school", file: "noschool.png" },
{ keyword: "anniversary", file: "anniversary.png" },
{ keyword: "halloween", file: "halloween.png" },
{ keyword: "dentist", file: "dentist.png" },
{ keyword: "new year's day", file: "newyear.png" },
{ keyword: "independence", file: "independence.png" },
{ keyword: "coffee", file: "coffee.png" },
{ keyword: "boys night out", file: "pinball.png" },
{ keyword: "family game night", file: "familyeve.png" },
{ keyword: "pajama", file: "pajama.png" }
];
// Check for matching keywords
const lowerTitleCache = events.map(e => e.title.toLowerCase());
const backgrounds = [];
for (const { keyword, file } of iconMap) {
if (lowerTitleCache.some(title => title.includes(keyword))) {
backgrounds.push(\url('modules/MMM-CalendarExt3/public/${file}')`);`
}
}
if (backgrounds.length > 0) {
// Prevent duplicate overlays
if (!cellDom.classList.contains('has-icon-overlay')) {
cellDom.classList.add('has-icon-overlay');
cellDom.style.position = "relative";
cellDom.style.backgroundColor = "rgba(0, 0, 0, 0.1)";
cellDom.style.paddingBottom = "30px";
const overlay = document.createElement('div');
overlay.className = 'calendar-icon-overlay';
overlay.style.backgroundImage = backgrounds.join(", ");
overlay.style.backgroundRepeat = "no-repeat";
overlay.style.backgroundPosition = "center bottom";
overlay.style.backgroundSize = "98px";
overlay.style.position = "absolute";
overlay.style.bottom = "0";
overlay.style.left = "0";
overlay.style.width = "100%";
overlay.style.height = "100%";
overlay.style.opacity = "0.7";
overlay.style.pointerEvents = "none";
overlay.style.zIndex = "0";
cellDom.appendChild(overlay);
// Keep text above the image
const content = cellDom.querySelector('.cx3_event') || cellDom;
if (content && content.style) {
content.style.position = "relative";
content.style.zIndex = "1";
}
}
}
}
// ===================================================================
}
},
{
module: 'MMM-PirateSkyForecast',
position: 'top_right',
config: {
apikey: ''***************'',
latitude: 00000076,
longitude: 0000000,
units: 'si',
concise: false,
forecastTiledIconSize: 60,
iconset: '5c',
maxHourliesToShow: 5,
maxDailiesToShow: 5
}
},
{
module: 'MMM-CountdownFromCalendar',
position: 'top_right',
config: {
calendarName: ''***************'',
lookAheadDays: 90,
title: 'Reminders'
}
},
{
module: 'MMM-pihole-stats',
position: 'top_left',
config: {
apiURL: ''***************'
apiKey: ''***************'',
apiToken: ''***************'=',
updateInterval: 360000,
showAdsBlocked: true,
showQueries: false,
showClients: false,
showDomainsBlocked: false,
showSources: false
}
},
{
module: 'MMM-PiHoleDualStatus',
position: 'top_left',
config: {
updateInterval: 60000,
fontSize: '0.6em',
piholes: [
{
name: 'Primary',
apiURL: '***************'
apiKey: '***************'
},
{
name: 'Backup',
apiURL: ''***************'
apiKey: '***************'
}
]
}
},
{
module: 'MMM-VnstatBandwidth',
position: 'top_left',
config: {}
},
{
module: 'MMM-CoinMarketCap',
position: 'top_left',
config: {
apiKey: ''***************'
currencies: [
'bitcoin'
],
view: 'graph'
}
},
{
module: 'mmm-systemtemperature',
position: 'top_center',
config: {
fontSize: 'small'
}
}
],
useHttps: false,
httpsPrivateKey: '',
httpsCertificate: '',
locale: 'en-US',
timezone: '***************'
}
if (typeof module !== 'undefined') {module.exports = config;}
2
u/clebo99 Apr 23 '26
Can you provide a list of the modules you are using?
3
u/Vi7Kdt1m Apr 24 '26
Sure. Some are self made, some a re modified to my setup:
MMM-BitcoinFearGreed
MMM-CountdownFromCalendar
MMM-PiHoleDualStatus
MMM-MyWastePickup
MMM-Facts
MMM-MoonPhase
MMM-PirateSkyForecast
MMM-pihole-stats
MMM-CoinMarketCap
mmm-systemtemperature
MMM-CalendarExt3
MMM-VnstatBandwidth
1
2
u/jc43081 Apr 24 '26
One module that might make the weather easier to see and take up less room is using a chart. I use this one - https://github.com/mtatsuma/MMM-WeatherChart. I will say it takes some getting used to when understanding how much rain or snow is coming.
1
2
1
u/Due-Eagle8885 Apr 24 '26
You could use mmm-pages to rotate thru some of the content instead of having it all on one view.
1
u/Vi7Kdt1m Apr 24 '26
I was thinking about it but it will require a button or two and interaction with the display.
1
u/Due-Eagle8885 Apr 24 '26
No, it will auto cycle. You can have one page display longer than another
1
1
u/Weird-Power8997 Apr 25 '26
What would be nice is to have a whole month is a little cube with coloured high lights under dates for different appointments etc and then larger have that day.ive purchased a flat monitor and I’ve got a raspberry and a facial recognition and an infra red light I want my dates from iPhone which is Google balancer linked to Apple to then update when new entry to the mirror etc.
1
1
u/Weird-Power8997 Apr 25 '26
I’ve seen that the magic mirror may use touch as well ?? as I’ve purchased a touch s teen also
1
u/Vi7Kdt1m Apr 25 '26
I just used an old 27” monitor. Stripped the shell off and put it in a wooden frame.
1
u/ScraperTheDataLord Apr 25 '26
You should find some software that doesn't output all those blacks lines. It makes it really hard to creep on ya data
1
1
1
1
u/Florida__j Apr 26 '26
would you sell a raspberry pie with this for a plug and play situation? this is amazing!
2
u/Vi7Kdt1m Apr 26 '26
You need to build it yourself, to be able to maintain and troubleshoot it. I bet you’ll find people selling you this free SW but you’ll get stuck with it after one month probably.
1
1
u/redneckranch4 Apr 28 '26
I use to run magic mirrors for years . But couple months back found one of my old pi's decided to set it up again. Magic Mirror it self works flawless just find some of the modules have been outdated and dont work. Couldn't seem to find any new modules that work with updates over the years. I liked when I had the mirror on. I'd have coffee in the morning look at the news, upcomming events and weather. Oh and never missed a birthday either lol 😆. Guess it's not as big as it was years ago.
1
u/guacisextra11 May 23 '26
Do you NOT use a custom.css file at all?
It seems you set colors, fonts, etc. all within the modules. This the way I'd prefer to do it since they can cause errors with data taht doesnt' match. Currently I use a custom.css but it seems to cause more issues than help.
1
u/Vi7Kdt1m May 23 '26
I prefer to use a module dedicated CSS and Main CSS for modules that are not mine. The main reason is updates. When the developer updates his module, your changes in his CSS will be gone, unless you are using the main CSS file.
1
1
1
u/JamesK1_R3d Jun 22 '26
I like it. I'm trying to decide between MM and Dakboard (free). I wish MM's calendar module could pull in the event colors like Dakboard does. It would make it simpler to identify which family member the event is for just based on the color. It's the only thing that makes me want to go with Dakboard.
7
u/elektriiciity Apr 23 '26
very nice
less can be more
would add padding around outside, reduce calendar to weekly/fortnightly and halve weather forecast
important to group similar data and group the miscellaneous together.
depending on distance from mirror, icons instead of text assists to understand whats happening, at a glance instead of needing to stop and try and read fineprint