├── .github ├── FUNDING.yml └── workflows │ └── autoupdate_develop.yaml ├── .gitignore ├── .prettierignore ├── .prettierrc.js ├── .vuepress ├── client.ts ├── components │ └── CarbonAds.vue ├── config.js ├── layouts │ └── Layout.vue ├── public │ ├── header.png │ ├── header.psd │ └── logo.png └── styles │ └── index.scss ├── README.md ├── about ├── LICENSE.md ├── contributing.md ├── donate.md ├── manifesto.md └── support.md ├── configuration ├── autostart.md ├── introduction.md ├── raspberry.md └── screenshots │ └── dualmon.png ├── cspell.config.json ├── development ├── core-module-file.md ├── documentation.md ├── helper-methods.md ├── introduction.md ├── logger.md ├── node-helper.md ├── notifications.md └── weather-provider.md ├── getting-started ├── installation.md ├── requirements.md └── upgrade-guide.md ├── modules ├── alert.md ├── animate.md ├── calendar.md ├── clock.md ├── compliments.md ├── configuration.md ├── customcss.md ├── helloworld.md ├── introduction.md ├── newsfeed.md ├── screenshots │ ├── animate.gif │ ├── clock.png │ ├── compliments.png │ ├── customEvents_transform_after.png │ ├── customEvents_transform_before.png │ ├── newsfeed.png │ ├── regions.png │ ├── weather_current.png │ └── weather_forecast.png ├── updatenotification.md └── weather.md ├── package-lock.json └── package.json /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: MichMich 2 | custom: ["https://magicmirror.builders/#donate"] 3 | -------------------------------------------------------------------------------- /.github/workflows/autoupdate_develop.yaml: -------------------------------------------------------------------------------- 1 | name: Merge master into develop 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - master 7 | types: 8 | - closed 9 | 10 | permissions: 11 | contents: write 12 | 13 | jobs: 14 | merge-master-back-to-develop: 15 | if: github.event.pull_request.merged == true 16 | timeout-minutes: 5 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: actions/checkout@v4 20 | - name: Merge master back to develop 21 | run: | 22 | git config --local user.email "actions@github.com" 23 | git config --local user.name "Github Actions" 24 | git fetch --unshallow 25 | git checkout develop 26 | git status 27 | git merge --no-ff --allow-unrelated-histories origin/master -m "Auto-merge master back to develop" 28 | git push 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea/ 3 | node_modules/ 4 | 5 | .vuepress/.cache 6 | .vuepress/.temp 7 | .vuepress/dist 8 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .vuepress -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ...require("prettier-config-vuepress"), 3 | proseWrap: "always", 4 | singleQuote: false, 5 | semi: true, 6 | }; 7 | -------------------------------------------------------------------------------- /.vuepress/client.ts: -------------------------------------------------------------------------------- 1 | import { defineClientConfig } from 'vuepress/client'; 2 | import Layout from './layouts/Layout.vue'; 3 | 4 | export default defineClientConfig({ 5 | layouts: { 6 | Layout, 7 | }, 8 | }) 9 | -------------------------------------------------------------------------------- /.vuepress/components/CarbonAds.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 81 | -------------------------------------------------------------------------------- /.vuepress/config.js: -------------------------------------------------------------------------------- 1 | import { defaultTheme } from '@vuepress/theme-default'; 2 | import { googleAnalyticsPlugin } from '@vuepress/plugin-google-analytics'; 3 | import { docsearchPlugin } from '@vuepress/plugin-docsearch'; 4 | import { viteBundler } from '@vuepress/bundler-vite'; 5 | 6 | export default { 7 | title: "MagicMirror² Docs", 8 | description: "The open source modular smart mirror platform.", 9 | bundler: viteBundler({}), 10 | theme: defaultTheme({ 11 | contributors: false, 12 | docsRepo: "MagicMirrorOrg/MagicMirror-Documentation", 13 | docsBranch: "master", 14 | editLinkText: "Help us improve this page!", 15 | logo: 'logo.png', 16 | navbar: [ 17 | { text: "Donate", link: "https://magicmirror.builders/donate" }, 18 | { text: "Discord", link: "https://discord.gg/J5BAtvx" }, 19 | { text: "Forum", link: "https://forum.magicmirror.builders" }, 20 | ], 21 | repo: "MagicMirrorOrg/MagicMirror", 22 | repoLabel: "GitHub", 23 | sidebar: [ 24 | { 25 | text: "Getting Started", 26 | collapsible: true, 27 | children: [ 28 | "/", 29 | "/getting-started/requirements.md", 30 | "/getting-started/installation.md", 31 | "/getting-started/upgrade-guide", 32 | ], 33 | }, 34 | { 35 | text: "Configuration", 36 | collapsible: true, 37 | children: [ 38 | "/configuration/introduction", 39 | "/configuration/autostart", 40 | "/configuration/raspberry", 41 | ], 42 | }, 43 | { 44 | text: "Modules", 45 | collapsible: true, 46 | children: [ 47 | "/modules/introduction", 48 | "/modules/configuration", 49 | { 50 | text: "Default Modules", 51 | collapsible: false, 52 | children: [ 53 | "/modules/alert", 54 | "/modules/calendar", 55 | "/modules/clock", 56 | "/modules/compliments", 57 | "/modules/helloworld", 58 | "/modules/newsfeed", 59 | "/modules/updatenotification", 60 | "/modules/weather", 61 | ], 62 | }, 63 | "/modules/animate" 64 | ], 65 | }, 66 | { 67 | text: "Module Development", 68 | collapsible: true, 69 | children: [ 70 | "/development/introduction.md", 71 | "/development/core-module-file.md", 72 | "/development/node-helper.md", 73 | "/development/helper-methods.md", 74 | "/development/logger.md", 75 | "/development/notifications.md", 76 | "/development/weather-provider.md", 77 | "/development/documentation.md", 78 | ], 79 | }, 80 | { 81 | text: "About", 82 | collapsible: true, 83 | children: [ 84 | "/about/manifesto", 85 | "/about/contributing", 86 | "/about/donate", 87 | "/about/support", 88 | "/about/LICENSE", 89 | ], 90 | }, 91 | ], 92 | }), 93 | markdown: { 94 | toc: { includeLevel: [2, 3, 4] }, 95 | }, 96 | locales: { 97 | "/": { 98 | lang: "en", 99 | }, 100 | }, 101 | plugins: [ 102 | googleAnalyticsPlugin({ 103 | id: "UA-1219071-59", 104 | }), 105 | docsearchPlugin({ 106 | apiKey: "96d207343bbb5e45068a1e3c8d141bb4", 107 | appId: "U3QOOOGLZR", 108 | indexName: "docs-magicmirror-builders", 109 | }), 110 | ], 111 | }; 112 | 113 | -------------------------------------------------------------------------------- /.vuepress/layouts/Layout.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 14 | -------------------------------------------------------------------------------- /.vuepress/public/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MagicMirrorOrg/MagicMirror-Documentation/691533aaaa1e272d194f5f60216e0751ba0bddb0/.vuepress/public/header.png -------------------------------------------------------------------------------- /.vuepress/public/header.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MagicMirrorOrg/MagicMirror-Documentation/691533aaaa1e272d194f5f60216e0751ba0bddb0/.vuepress/public/header.psd -------------------------------------------------------------------------------- /.vuepress/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MagicMirrorOrg/MagicMirror-Documentation/691533aaaa1e272d194f5f60216e0751ba0bddb0/.vuepress/public/logo.png -------------------------------------------------------------------------------- /.vuepress/styles/index.scss: -------------------------------------------------------------------------------- 1 | :root { 2 | scroll-behavior: smooth; 3 | } 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Introduction 3 | --- 4 | 5 | ![MagicMirror²: The open source modular smart mirror platform. ](./.vuepress/public/header.png) 6 | 7 |

8 | 9 | License 10 | 11 | GitHub Actions 12 | Build Status 13 | 14 | GitHub stars 15 | 16 |

17 | 18 | [**MagicMirror²**](https://magicmirror.builders/) is an open source modular 19 | smart mirror platform. With a growing list of installable modules, the 20 | **MagicMirror²** allows you to convert your hallway or bathroom mirror into your 21 | personal assistant. **MagicMirror²** is built by the creator of 22 | [the original MagicMirror](https://michaelteeuw.nl/tagged/magicmirror) with the 23 | incredible help of a 24 | [growing community of contributors](https://github.com/MagicMirrorOrg/MagicMirror/graphs/contributors). 25 | 26 | MagicMirror² focuses on a modular plugin system and uses 27 | [Electron](https://www.electronjs.org/) as an application wrapper. So no more 28 | web server or browser installs necessary! 29 | 30 |

31 | MagPi Top 50 32 |

33 | -------------------------------------------------------------------------------- /about/LICENSE.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: License 3 | --- 4 | 5 | # The MIT License (MIT) 6 | 7 | Copyright © 2016-2025 Michael Teeuw 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy of 10 | this software and associated documentation files (the “Software”), to deal in 11 | the Software without restriction, including without limitation the rights to 12 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 13 | the Software, and to permit persons to whom the Software is furnished to do so, 14 | subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all 17 | copies or substantial portions of the Software. 18 | 19 | **The software is provided “as is”, without warranty of any kind, express or 20 | implied, including but not limited to the warranties of merchantability, fitness 21 | for a particular purpose and noninfringement. In no event shall the authors or 22 | copyright holders be liable for any claim, damages or other liability, whether 23 | in an action of contract, tort or otherwise, arising from, out of or in 24 | connection with the software or the use or other dealings in the software.** 25 | -------------------------------------------------------------------------------- /about/contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Contributions of all kinds are welcome, not only in the form of code but also 4 | with regards bug reports and documentation. 5 | 6 | Please keep the following in mind: 7 | 8 | - **Bug Reports**: Make sure you're running the latest version. If the issue(s) 9 | still persist: please open a clearly documented issue with a clear title. 10 | - **Minor Bug Fixes**: Please send a pull request with a clear explanation of 11 | the issue or a link to the issue it solves. 12 | - **Major Bug Fixes**: please discuss your approach in an GitHub issue before 13 | you start to alter a big part of the code. 14 | - **New Features**: please please discuss in a GitHub issue before you start to 15 | alter a big part of the code. Without discussion upfront, the pull request 16 | will not be accepted / merged. 17 | 18 | Thanks for your help in making MagicMirror² better! 19 | 20 | ## Working Language 21 | 22 | To ensure inclusivity, collaboration, and accessibility for contributors from 23 | all around the world, we have chosen English as the working language for this 24 | project. Here are the key reasons behind this decision: 25 | 26 | 1. Global Accessibility: English is widely recognized and understood, enabling a 27 | diverse group of contributors to participate, share ideas, and collaborate 28 | effectively without language barriers. 29 | 2. Uniform Documentation: Using English for documentation ensures that all 30 | project materials are consistent and comprehensible to the majority of 31 | developers, regardless of their native language. 32 | 3. Broader Community Engagement: By using a common language, we can engage with 33 | a broader community, attracting talent and contributions from various regions 34 | and backgrounds. 35 | 4. Resource Availability: Most technical resources, tutorials, and libraries are 36 | available in English, providing contributors with a wealth of information and 37 | tools to support their work. 38 | 39 | We understand that choosing English as the working language is not the perfect 40 | solution for everyone, as it may present challenges for non-English speakers. 41 | However, it is the best compromise to ensure effective communication and 42 | collaboration across our diverse and global community. 43 | 44 | If you are not comfortable with English and cannot use translation tools, please 45 | feel free to use your native language in the forum. However, please keep in mind 46 | that asking questions in English is more likely to get you help quickly. 47 | 48 | We appreciate your understanding and cooperation in using English as the working 49 | language. Together, let's build something amazing! 50 | -------------------------------------------------------------------------------- /about/donate.md: -------------------------------------------------------------------------------- 1 | # Donate 2 | 3 | MagicMirror² is open source and free. That doesn't mean we don't need any money. 4 | 5 | Please consider a donation to help us cover the ongoing costs like webservers 6 | and email services. If we receive enough donations we might even be able to free 7 | up some working hours and spend some extra time improving the MagicMirror² core. 8 | 9 | To donate, please follow 10 | [this](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=G5D8E9MR5DTD2&source=url) 11 | link. 12 | -------------------------------------------------------------------------------- /about/manifesto.md: -------------------------------------------------------------------------------- 1 | # MagicMirror² Manifesto 2 | 3 | The following core principles form the foundation of MagicMirror² and guide our 4 | decisions and actions. They reflect the project’s commitment to simplicity, 5 | accessibility, and community-driven innovation. 6 | 7 | ## Vision 8 | 9 | To empower Raspberry Pi enthusiasts and developers of all levels by providing a 10 | platform that combines **simplicity** and **magic**, inspiring curiosity and 11 | collaboration in open-source development. 12 | 13 | ## Mission 14 | 15 | - **Preserve** the core philosophy of simplicity, ensuring that users can 16 | confidently modify and experiment with the software. 17 | - **Inspire** contributors by transforming MagicMirror² into an approachable 18 | entry point into the world of software development. 19 | - **Advance** the platform continuously while keeping accessibility and 20 | modularity at its heart. 21 | 22 | ## Core Principles 23 | 24 | - **Accessibility for All**: MagicMirror² strives to be the ultimate starter 25 | project for Raspberry Pi enthusiasts. Whether you’re a beginner taking your 26 | first steps or an experienced developer looking for a creative outlet, 27 | MagicMirror² aims to be intuitive and welcoming. 28 | - **Fostering Learning**: The project is not just about delivering a 29 | product—it’s about empowering users to explore, learn, and contribute to 30 | open-source development. We believe in inspiring curious minds to step out of 31 | their comfort zones and try new things. 32 | - **Modular and Open**: MagicMirror² is designed to be modular, allowing 33 | contributors to easily add or remove features. Each module reflects the 34 | diverse creativity of the community, while the project remains open to new 35 | ideas and improvements. 36 | - **Simplicity as a Foundation**: While we embrace technological advancements, 37 | simplicity remains a basic cornerstone of the project. As the project’s 38 | founder, [stated](https://github.com/MagicMirrorOrg/MagicMirror/issues/1174): 39 | 40 | > _We could use a powerful framework like Vue to ramp up the development 41 | > speed. We could use SASS for better/easier CSS implementations. ... But the 42 | > big downside of these changes is that it over complicates things: a user no 43 | > longer will be able to open just one file and make a small modification and 44 | > see how it works out._ --Michael Teeuw 45 | 46 | This principle ensures that MagicMirror² remains approachable, empowering 47 | users to take control of their projects with confidence. 48 | 49 | - **Collaborative Growth**: MagicMirror² thrives on collaboration. Contributions 50 | from the community—whether through code, feedback, or ideas—drive the project 51 | forward. We aim to create an environment where users feel valued and 52 | encouraged to contribute. 53 | 54 | ## Inspiring Contribution 55 | 56 | MagicMirror² is more than just a tool – it’s a platform that invites users to 57 | become creators. By keeping the system accessible and open, it motivates 58 | individuals to step beyond being passive users and to actively contribute to the 59 | project. 60 | 61 | Although bundled versions and pre-packaged solutions may seem convenient, they 62 | risk suppressing users' curiosity. As Michael has highlighted, _"users won’t be 63 | motivated to take a peek under the hood. They will just remain 'users'."_ 64 | MagicMirror² challenges this dynamic by encouraging even non-technical users to 65 | explore, learn, and take their first steps into software development. 66 | 67 | Through this philosophy, MagicMirror² not only provides functionality but 68 | fosters a community of learners, innovators, and collaborators – ensuring that 69 | its magic is driven by the passion and creativity of its contributors. 70 | 71 | ## Future Directions 72 | 73 | Building on our philosophy of fostering contributions, we aim to continue 74 | evolving MagicMirror² with the active involvement of its community. Each new 75 | feature and improvement will stay true to the spirit of collaboration and 76 | openness that defines this project. 77 | -------------------------------------------------------------------------------- /about/support.md: -------------------------------------------------------------------------------- 1 | # Support 2 | 3 | ## Forum 4 | 5 | The community around the MagicMirror² is constantly growing. We even have a 6 | [forum](https://forum.magicmirror.builders) now where you can share your ideas, 7 | ask questions, help others and get inspired by other builders. We would love to 8 | see you there! 9 | 10 | ## Discord 11 | 12 | If you prefer chat to slow talk, please join our 13 | [Discord channel](https://discord.gg/J5BAtvx). 14 | -------------------------------------------------------------------------------- /configuration/autostart.md: -------------------------------------------------------------------------------- 1 | # Autostart your MagicMirror² 2 | 3 | The methods below describe ways to automatically start your MagicMirror² on 4 | boot, and even ways to keep it running in case of a failure. 5 | 6 | ## Using PM2 7 | 8 | PM2 is a production process manager for Node.js applications with a built-in 9 | load balancer. It allows you to keep applications alive forever, to reload them 10 | without downtime and to facilitate common system admin tasks. In this case we 11 | will use it to keep a shell script running. 12 | 13 | ### Install PM2 14 | 15 | Install PM2 using NPM: 16 | 17 | ```shell 18 | sudo npm install -g pm2 19 | ``` 20 | 21 | ### Starting PM2 on Boot 22 | 23 | To make sure PM2 can do its job when (re)booting your operating system, it needs 24 | to be started on boot. Luckily, PM2 has a handy helper for this. 25 | 26 | ```shell 27 | pm2 startup 28 | ``` 29 | 30 | PM2 will now show you a command you need to execute. 31 | 32 | ### Make a MagicMirror² start script 33 | 34 | To use PM2 in combination with MagicMirror², we need to make a simple shell 35 | script. Preferable, we put this script outside the MagicMirror² folder to make 36 | sure it won't give us any issues if we want to upgrade the mirror. 37 | 38 | ```shell 39 | cd ~ 40 | nano mm.sh 41 | ``` 42 | 43 | Add the following lines: 44 | 45 | ```shell 46 | cd ./MagicMirror 47 | DISPLAY=:0 npm run start 48 | ``` 49 | 50 | Save and close, using the commands `CTRL-O` and `CTRL-X`. Now make sure the 51 | shell script is executable by performing the following command: 52 | 53 | ```shell 54 | chmod +x mm.sh 55 | ``` 56 | 57 | You are now ready to the MagicMirror² using this script using PM2. 58 | 59 | ### Starting your MagicMirror² with PM2 60 | 61 | Simply start your mirror with the following command: 62 | 63 | ```shell 64 | pm2 start mm.sh 65 | ``` 66 | 67 | You mirror should now boot up and appear on your screen after a few seconds. 68 | 69 | ### Enable restarting of the MagicMirror² script 70 | 71 | To make sure the MagicMirror² restarts after rebooting, you need to save the 72 | current state of all scripts running via PM2. To do this, execute the following 73 | command 74 | 75 | ```shell 76 | pm2 save 77 | ``` 78 | 79 | And that's all there is! Your MagicMirror² should now reboot after start, and 80 | restart after any failure. 81 | 82 | ### Controlling your MagicMirror² via PM2 83 | 84 | With your MagicMirror running via PM2, you have some handy tools at hand: 85 | 86 | #### Restarting your MagicMirror² 87 | 88 | ```shell 89 | pm2 restart mm 90 | ``` 91 | 92 | #### Stopping your MagicMirror² 93 | 94 | ```shell 95 | pm2 stop mm 96 | ``` 97 | 98 | #### Show the MagicMirror² logs 99 | 100 | ```shell 101 | pm2 logs mm 102 | ``` 103 | 104 | #### Show the MagicMirror² process information 105 | 106 | ```shell 107 | pm2 show mm 108 | ``` 109 | 110 | ## Using systemd/systemctl 111 | 112 | Note: Systemctl is a control interface for systemd, a powerful service manager 113 | often found in full Linux systems. This approach is most like only applicable 114 | for those using the "server only" setup running on a linux server. 115 | 116 | ### Create service file 117 | 118 | To start, you'll need to create a config file via your editor of choice (nano 119 | used in these examples): 120 | 121 | ```shell 122 | sudo nano /etc/systemd/system/magicmirror.service 123 | ``` 124 | 125 | Place the below text into your new file, modify as needed (see notes below) then 126 | save & exit. Notes: The example assumes MagicMirror is installed in the 127 | "WorkingDirectory" of "/home/server/MagicMirror/" and your node install is 128 | located at "/usr/bin/node" (run `which node` if you're unsure where to find 129 | node) this means your full manual start command would be "/usr/bin/node 130 | /home/server/MagicMirror/serveronly". While you almost certainly don't type this 131 | all out when you run manually, systemctl requires full paths. This example also 132 | assumes you have an existing Linux user of "server", but any user will do. 133 | "root" will certainly work but has the potential to do more damage, so you 134 | should avoid it if possible. 135 | 136 | ```ini 137 | [Unit] 138 | Description=MagicMirror 139 | After=network.target 140 | StartLimitIntervalSec=0 141 | 142 | [Service] 143 | Type=simple 144 | Restart=always 145 | RestartSec=1 146 | User=server 147 | WorkingDirectory=/home/server/MagicMirror/ 148 | ExecStart=/usr/bin/node serveronly 149 | 150 | [Install] 151 | WantedBy=multi-user.target 152 | ``` 153 | 154 | ### Control MM with systemctl 155 | 156 | Now try starting MM with the commands below. If start is successful work, use 157 | the 'enable' command below to automatically start when MM fails or is rebooted. 158 | If MM does not start, use the "status" command below to see most recent errors. 159 | 160 | Note: For any of the below commands 'magicmirror.service' can be replaced with 161 | `magicmirror` as systemd will automatically look for `\*.service` 162 | 163 | #### Start MM with systemctl 164 | 165 | ```shell 166 | sudo systemctl start magicmirror.service 167 | ``` 168 | 169 | #### Stop MM with systemctl 170 | 171 | ```shell 172 | sudo systemctl stop magicmirror.service 173 | ``` 174 | 175 | #### To check the status of MagicMirror² 176 | 177 | ```shell 178 | sudo systemctl status magicmirror.service 179 | ``` 180 | 181 | #### Allow autostart MagicMirror² on boot 182 | 183 | Note: does not start immediately, need to run start command or reboot 184 | 185 | ```shell 186 | sudo systemctl enable magicmirror.service 187 | ``` 188 | 189 | #### Disable autostart of MagicMirror² 190 | 191 | ```shell 192 | sudo systemctl disable magicmirror.service 193 | ``` 194 | 195 | ### Autostart browser for server mode 196 | 197 | Create file `/home/server/.config/lxsession/LXDE-pi/autostart` with the 198 | following contents: 199 | 200 | ```shell 201 | @lxpanel --profile LXDE-pi 202 | @pcmanfm --desktop --profile LXDE-pi 203 | @xscreensaver -no-splash 204 | @point-rpi 205 | @sh /home/server/bin/start-chromium.sh 206 | ``` 207 | 208 | Create file `/home/server/bin/start-chromium.sh` with the following contents: 209 | 210 | ```shell 211 | #!/bin/sh 212 | 213 | set -e 214 | 215 | CHROMIUM_TEMP=~/tmp/chromium 216 | rm -Rf ~/.config/chromium/ 217 | rm -Rf $CHROMIUM_TEMP 218 | mkdir -p $CHROMIUM_TEMP 219 | 220 | chromium-browser \ 221 | --disable \ 222 | --disable-translate \ 223 | --disable-infobars \ 224 | --disable-suggestions-service \ 225 | --disable-save-password-bubble \ 226 | --disk-cache-dir=$CHROMIUM_TEMP/cache/ \ 227 | --user-data-dir=$CHROMIUM_TEMP/user_data/ \ 228 | --start-maximized \ 229 | --kiosk http://localhost:8080 & 230 | ``` 231 | -------------------------------------------------------------------------------- /configuration/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | ## Basic Configuration of MagicMirror² 4 | 5 | 1. Go to your configuration directory: In Bash/linux, it'll be in 6 | `~/MagicMirror/config/` 7 | 8 | 2. Create and edit a config.js by using your editor of choice. 9 | 10 | 3. Minimum configuration requires the following: 11 | 12 | ```js 13 | let config = { 14 | modules: [ 15 | { 16 | module: "clock", 17 | position: "fullscreen_above", 18 | config: {}, 19 | }, 20 | ], 21 | }; 22 | ``` 23 | 24 | See [module configuration](/modules/configuration.md) for more information 25 | and examples. 26 | 27 | 4. Run your magic mirror. Refer back to 28 | [installation](/getting-started/installation.md) if you're not sure how to do 29 | so. 30 | 31 | ## More useful configuration of your MagicMirror 32 | 33 | These directions assume a linux/bash style command line, and previous 34 | instructions followed. If not, please insert the path directly from your 35 | installation. 36 | 37 | 1. Copy `~/MagicMirror/config/config.js.sample` to 38 | `~/MagicMirror/config/config.js`. \ 39 | **Note:** If you used a third-party installer script, this step may already 40 | have been done for you. 41 | 42 | 2. Modify your required settings using your preferred editor. `nano` is the 43 | easiest. 44 | 45 | 3. You can check your configuration running `npm run config:check` in 46 | `~/MagicMirror`. 47 | 48 | The following properties can be configured, place them above the modules item: 49 | 50 | | **Option** | **Description** | Default Value | 51 | | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | 52 | | `port` | The port on which the MagicMirror² server will run on. This may need to be changed in specific advanced installations, below. | 8080 | 53 | | `address` | The _interface_ ip address on which to accept connections. The default prevents exposing the built-in webserver to machines on the local network. To expose it to other machines, use: `0.0.0.0`. | `localhost` | 54 | | `ipWhitelist` | The list of IPs from which you are allowed to access the MagicMirror². Add your IP when needed. You can also specify IP ranges with subnet masks (`["127.0.0.1", "127.0.0.1/24"]`) or directly with (`["127.0.0.1", ["192.168.0.1", "192.168.0.100"]]`). Set `[]` to allow all IP addresses. For more information see: [ipWhitelist HowTo](https://forum.magicmirror.builders/topic/1326/ipwhitelist-howto) | `["127.0.0.1", "::ffff:127.0.0.1", "::1"]` | 55 | | `zoom` | This allows to scale the mirror contents with a given zoom factor. | `1.0` | 56 | | `language` | The language of the interface. (Note: Not all elements will be localized.) Possible values are `en`, `nl`, `ru`, `fr`, etc. for the full list see: [List of ISO 639-1 codes](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) | `en` | 57 | | `timeFormat` | The form of time notation that will be used. Possible values are `12` or `24`. | 24 | 58 | | `units` | The units that will be used in the default weather modules. Possible values are `metric` or `imperial`. | `metric` | 59 | | `electronOptions` | An optional array of Electron (browser) options. This allows configuration of e.g. the browser screen size and position (example: `electronOptions: { fullscreen: false, width: 800, height: 600 }`). Kiosk mode can be enabled by setting `kiosk: true`, `autoHideMenuBar: false` and `fullscreen: false`. More options can be found [here](https://github.com/electron/electron/blob/master/docs/api/browser-window.md). This will most likely be used in advanced installations, below. | [] | 60 | | `electronSwitches` | An optional array of Electron switches. This allows configuration of electron app itself.
This properties will not affect the `serveronly` mode. Usually normal `MM` users don't need this property, but if you are a hard-core hacker, you might need this to handle Electron itself over `MagicMirror` provides. More options can be found [here](https://www.electronjs.org/docs/latest/api/command-line-switches) (Not all available switches are described there.)
example:`electronSwitches:["enable-transparent-visuals", "disable-gpu"];` | [] | 61 | | `customCss` | The path of the `custom.css` stylesheet. The default is `css/custom.css`. | `css/custom.css` | 62 | 63 | After the above options, you will then add modules. See 64 | [module configuration](/modules/configuration.md) for more information. 65 | 66 | ### Advanced configuration and frequently asked how to configure examples 67 | 68 | #### Bash Environment variables 69 | 70 | There are two environment variables that override part or all of config.js. They 71 | are: 72 | 73 | | Environment Variable Name | Use | 74 | | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | 75 | | MM_CONFIG_FILE | This specifies an alternate configuration file for the system. This is useful when running multiple mirrors on the same device. This does not work with the template option below. NOTE: this file **_MUST_** be located in a directory within the MagicMirror directory. Ideally, place any config file in the config subdirectory. | 76 | | MM_PORT | This specifies an alternate TCP/IP port, overriding "port" item within the config file. This is useful for testing to see if the product will run using another port. | 77 | | mmFetchTimeout | time in milliseconds for fetch timeout. default (30000)

this value can be used to adjust the nodejs fetch function timeout value (default 10 seconds) for all node_helper modules that use fetch() | 78 | 79 | #### Examples of use 80 | 81 | You have created two config files, named config.js and config2.js 82 | 83 | By default, you would use config.js with a bash script (mm.sh): 84 | 85 | ```bash 86 | cd ~/MagicMirror 87 | npm run start 88 | ``` 89 | 90 | To use the 2nd configuration file, use a bash script like this (mm2.sh): 91 | 92 | ```bash 93 | cd ~/MagicMirror 94 | export MM_CONFIG_FILE=config/config2.js 95 | npm run start 96 | ``` 97 | 98 | To change the port: 99 | 100 | ```bash 101 | cd ~/MagicMirror 102 | export MM_PORT=8081 103 | npm run start 104 | ``` 105 | 106 | You can run `npm run config:check` on your 2nd configuration file by typing the 107 | export line in first, example: 108 | 109 | ```bash 110 | export MM_CONFIG_FILE=config/config2.js 111 | npm run config:check 112 | ``` 113 | 114 | ```log 115 | [26.12.2023 18:13.12.972] [INFO] Checking file... /home//MagicMirror/config/config2.js 116 | [26.12.2023 18:13.13.062] [INFO] Your configuration file doesn't contain syntax errors :) 117 | ``` 118 | 119 | ### Configuration Template system 120 | 121 | `config.js.template` can be used instead of `config.js`. This allows you to use 122 | variables to replace hardcoded options. When starting MagicMirror² a `config.js` 123 | is created from `config.js.template` and the variables are resolved. This is 124 | most useful for tech support provided on the 125 | [forums](http://forum.magicmirror.builders) and sharing your configuration. 126 | Note: You cannot use this with MM_CONFIG_FILE above at this time. 127 | 128 | Variables must be inserted as `${MY_VARIABLE}`, examples: 129 | 130 | `config.js.template`: 131 | 132 | ```javascript 133 | let config = { 134 | address: "${MY_ADDRESS}", 135 | port: ${MY_PORT}, 136 | useHttps: ${MY_HTTPS}, 137 | }; 138 | /*************** DO NOT EDIT THE LINE BELOW ***************/ 139 | if (typeof module !== "undefined") {module.exports = config;} 140 | ``` 141 | 142 | would become 143 | 144 | `config.js`: 145 | 146 | ```javascript 147 | let config = { 148 | address: "localhost", 149 | port: 8080, 150 | useHttps: false, 151 | }; 152 | /*************** DO NOT EDIT THE LINE BELOW ***************/ 153 | if (typeof module !== "undefined") { 154 | module.exports = config; 155 | } 156 | ``` 157 | 158 | #### Defining variables 159 | 160 | There are 2 ways to define variables, you can mix as needed or desired. If a 161 | variable is defined in both ways the linux environment variable is used. 162 | 163 | #### Using a `config.env` file 164 | 165 | This file must be in the same folder as the `config.js.template` and contains 166 | the variables, using the example from above: 167 | 168 | File content of `config.env`: 169 | 170 | ```log 171 | MY_ADDRESS=localhost 172 | MY_PORT=8080 173 | MY_HTTPS=false 174 | ``` 175 | 176 | #### Using linux environment variables 177 | 178 | define them before you start MagicMirror², in a bash script, for example: 179 | 180 | ```bash 181 | cd ~/MagicMirror 182 | export MY_ADDRESS=localhost 183 | export MY_PORT=8080 184 | export MY_HTTPS=false 185 | npm run start 186 | ``` 187 | 188 | ### Using `electronOptions` 189 | 190 | The most common use for `electronOptions` is a dual monitor setup on a Raspberry 191 | Pi 4 or greater. To do so, you can launch a second MagicMirror and use 192 | `electronOptions` to move it over to the next monitor. For example: 193 | 194 | You have two 1920x1080 monitors set up in the Pi as sitting next to each other: 195 | ![Screen-Layout-Editor](./screenshots/dualmon.png) 196 | 197 | To move the pi to the second monitor, use this: 198 | 199 | ```js 200 | let config = { 201 | electronOptions: { x: 1920 }, 202 | ... 203 | ``` 204 | 205 | ### A Couple of Real World Examples 206 | 207 | #### Two Screens 208 | 209 | A user has two monitors running on a Pi4B. User wants to show cameras on one 210 | monitor, and wants to show informational panels on the other. Monitors are set 211 | up as above. 212 | 213 | User would have to set up two config files, and two starting scripts to do so. 214 | User would use method of choice to launch starting scripts (e.g.: `PM2`). 215 | 216 | Starting Script 1 (mm.sh): 217 | 218 | ```bash 219 | cd ~/MagicMirror 220 | npm run start 221 | ``` 222 | 223 | Starting Script 2 (mm2.sh): 224 | 225 | ```bash 226 | cd ~/MagicMirror 227 | export MM_CONFIG_FILE=config/config2.js 228 | npm run start 229 | ``` 230 | 231 | Configuration file 1 (config.js): 232 | 233 | ```js 234 | let config = { 235 | address: "0.0.0.0", // Can be whatever you set as your original. 236 | port: 8080, // Must be different than the other configuration file. 237 | ipWhitelist: [], // Can be whatever you set as your original. 238 | language: "en", 239 | timeFormat: 12, 240 | units: "imperial", 241 | //logLevel: ["INFO", "LOG", "WARN", "ERROR", "DEBUG"], 242 | modules: [ 243 | (insert module configurations here) 244 | ] // end of modules 245 | }; // end of config variable. 246 | /*************** DO NOT EDIT BELOW ***************/ 247 | if (typeof module !== "undefined") { 248 | module.exports = config; 249 | } 250 | ``` 251 | 252 | Configuration file 2 (config2.js): 253 | 254 | ```js 255 | let config = { 256 | electronOptions: { x: 1920 }, 257 | address: "0.0.0.0", // can be whatever you set as your original. 258 | port: 8081, // Must be different than the other configuration file. 259 | ipWhitelist: [], // Can be whatever you set as your original. 260 | language: "en", 261 | timeFormat: 12, 262 | units: "imperial", 263 | //logLevel: ["INFO", "LOG", "WARN", "ERROR", "DEBUG"], 264 | modules: [ 265 | (insert module configurations here) 266 | ] // end of modules 267 | }; // end of config variable. 268 | /*************** DO NOT EDIT BELOW ***************/ 269 | if (typeof module !== "undefined") { 270 | module.exports = config; 271 | } 272 | ``` 273 | 274 | #### config.js.template example 275 | 276 | User likes to help German language users in the forums. As such, he wants to be 277 | able to paste bits of his config.js into the forums to show as an example, but 278 | don't want to share his private data, and has a hard time remembering to remove 279 | them from the config.js file. 280 | 281 | `config.js.template`: 282 | 283 | ```javascript 284 | let config = { 285 | address: "0.0.0.0", 286 | port: 8080, 287 | ipWhitelist: [], 288 | 289 | language: "de", 290 | logLevel: ["INFO", "LOG", "WARN", "ERROR"], 291 | timeFormat: 24, 292 | units: "metric", 293 | 294 | modules: [ 295 | { 296 | module: "MMM-RAIN-MAP", 297 | position: "bottom_left", 298 | config: { 299 | animationSpeedMs: 400, 300 | colorizeTime: false, 301 | defaultZoomLevel: 8, 302 | displayTime: true, 303 | displayClockSymbol: true, 304 | displayOnlyOnRain: false, 305 | extraDelayLastFrameMs: 2000, 306 | markers: [ 307 | { lat: ${LAT}, lng: ${LON}, color: "black" }, 308 | ], 309 | mapPositions: [ 310 | { lat: ${LAT}, lng: ${LON}, zoom: 9, loops: 1 }, 311 | { lat: ${LAT}, lng: ${LON}, zoom: 8, loops: 1 }, 312 | { lat: ${LAT}, lng: ${LON}, zoom: 7, loops: 1 }, 313 | { lat: ${LAT}, lng: ${LON}, zoom: 6, loops: 1 }, 314 | ], 315 | mapUrl: "${MAPBOX_URL}", 316 | mapHeight: "320px", 317 | mapWidth: "520px", 318 | updateIntervalInSeconds: 300, 319 | } 320 | }, 321 | { 322 | module: "MMM-Strava", 323 | header: "Strava", 324 | position: "bottom_left", 325 | config: { 326 | client_id: "16228", 327 | client_secret: "${STRAVA_API_KEY}", 328 | activities: ["ride"], 329 | period: "recent", 330 | stats: ["count", "distance", "elevation", "achievements"], 331 | auto_rotate: true, 332 | updateInterval: 20000, 333 | reloadInterval: 3600000, 334 | showPrivateStats: true, 335 | limitPrivateStats: 1200, 336 | digits: 0 337 | } 338 | }, 339 | { 340 | module: "MMM-OpenWeatherForecast", 341 | header: "Wetter", 342 | position: "top_center", 343 | config: { 344 | apikey: "${OPENWEATHER_API_KEY}", 345 | latitude: "${LAT}", 346 | longitude: "${LON}", 347 | showHourlyForecast: false, 348 | colored: false, 349 | iconset: "3c", 350 | label_days: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"], 351 | concise: false, 352 | forecastHeaderText: "", 353 | label_sunriseTimeFormat: "k:mm", 354 | label_high: "", 355 | label_low: "", 356 | displayKmhForWind: true 357 | } 358 | }, 359 | { 360 | module: "calendar", 361 | header: "Termine", 362 | position: "top_right", 363 | config: { 364 | timeFormat: "absolute", 365 | showEnd: false, 366 | dateFormat: "DD.MM.", 367 | maximumEntries: 10, 368 | maximumNumberOfDays: 70, 369 | colored: true, 370 | calendars: [ 371 | { 372 | symbol: "subway", 373 | url: "${CAL_URL1}" 374 | }, 375 | { 376 | symbol: "cake-candles", 377 | url: "${CAL_URL2}" 378 | }, 379 | { 380 | symbol: "angle-right", 381 | color: "#999999", 382 | url: "${CAL_URL3}" 383 | } 384 | ] 385 | } 386 | }, 387 | ] 388 | }; 389 | 390 | /*************** DO NOT EDIT THE LINE BELOW ***************/ 391 | if (typeof module !== "undefined") {module.exports = config;} 392 | ``` 393 | 394 | Matching `config.env` example (fake urls and locations): 395 | 396 | ```bash 397 | LAT=0.0 398 | LON=0.0 399 | MAPBOX_URL="http://example.url/1458562" 400 | STRAVA_API_KEY="FakeKey1234" 401 | OPENWEATHER_API_KEY="FakeKey4321" 402 | CAL_URL1="https://calendar.google.com/calendar/ical/example@example.example/private-fakeaddress12445812581119058955b/basic.ics" 403 | CAL_URL2="https://calendar.google.com/calendar/ical/example@example.example/private-fakeaddress2445812581119058955b/basic.ics" 404 | CAL_URL3="https://calendar.google.com/calendar/ical/example@example.example/private-fakeaddress32445812581119058955b/basic.ics" 405 | ``` 406 | 407 | For other help with setting up a more complex Mirror, please visit our 408 | [forum](https://forum.magicmirror.builders). 409 | -------------------------------------------------------------------------------- /configuration/raspberry.md: -------------------------------------------------------------------------------- 1 | # Raspberry Specific 2 | 3 | For now take a look at 4 | [the wiki page](https://github.com/MagicMirrorOrg/MagicMirror/wiki/Configuring-the-Raspberry-Pi). 5 | -------------------------------------------------------------------------------- /configuration/screenshots/dualmon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MagicMirrorOrg/MagicMirror-Documentation/691533aaaa1e272d194f5f60216e0751ba0bddb0/configuration/screenshots/dualmon.png -------------------------------------------------------------------------------- /cspell.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2", 3 | "language": "en", 4 | "words": [ 5 | "anyfileorfolder", 6 | "apikey", 7 | "clientonly", 8 | "iconset", 9 | "inclusivity", 10 | "infobars", 11 | "LXDE", 12 | "lxpanel", 13 | "lxsession", 14 | "magicmirror", 15 | "MAPBOX", 16 | "meteo", 17 | "modulename", 18 | "newsfeed", 19 | "nohup", 20 | "päästä", 21 | "Päättyy", 22 | "pcmanfm", 23 | "sdetweil", 24 | "serveronly", 25 | "Slutar", 26 | "STRAVA", 27 | "Subclassable", 28 | "subclassing", 29 | "Teeuw", 30 | "Termine", 31 | "weatherutils", 32 | "xscreensaver", 33 | "yourprovider" 34 | ], 35 | "ignorePaths": [ 36 | "node_modules/**", 37 | "modules/**", 38 | "vendor/node_modules/**", 39 | "translations/**", 40 | "tests/mocks/**", 41 | "tests/e2e/modules/clock_es_spec.js", 42 | "fonts/roboto.css" 43 | ], 44 | "dictionaries": ["node"] 45 | } 46 | -------------------------------------------------------------------------------- /development/core-module-file.md: -------------------------------------------------------------------------------- 1 | # The Core module file 2 | 3 | This is the script in which the module will be defined. This script is required 4 | in order for the module to be used. In it's most simple form, the core module 5 | file must be named after the module (`modulename.js`) and must contain: 6 | 7 | ```javascript 8 | Module.register("modulename", {}); 9 | ``` 10 | 11 | Of course, the above module would not do anything fancy, so it's good to look at 12 | one of the simplest modules: **helloworld**: 13 | 14 | ```javascript 15 | //helloworld.js: 16 | 17 | Module.register("helloworld", { 18 | // Default module config. 19 | defaults: { 20 | text: "Hello World!", 21 | }, 22 | 23 | // Override dom generator. 24 | getDom: function () { 25 | const wrapper = document.createElement("div"); 26 | wrapper.innerHTML = this.config.text; 27 | return wrapper; 28 | }, 29 | }); 30 | ``` 31 | 32 | As you can see, the `Module.register()` method takes two arguments: the name of 33 | the module and an object with the module properties. 34 | 35 | ## Available module instance properties 36 | 37 | After the module is initialized, the module instance has a few available module 38 | properties: 39 | 40 | | Instance Property | Type | Description | 41 | | :---------------- | :------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 42 | | `this.name` | String | The name of the module. | 43 | | `this.identifier` | String | This is a unique identifier for the module instance. | 44 | | `this.hidden` | Boolean | This represents if the module is currently hidden (faded away). | 45 | | `this.config` | Boolean | The configuration of the module instance as set in the user's `config.js` file. This config will also contain the module's defaults if these properties are not over-written by the user config. | 46 | | `this.data` | Object | The data object contain additional metadata about the module instance. (See below) | 47 | 48 | The `this.data` data object contain the following metadata: 49 | 50 | - `data.classes` - The classes which are added to the module dom wrapper. 51 | - `data.file` - The filename of the core module file. 52 | - `data.path` - The path of the module folder. 53 | - `data.header` - The header added to the module. 54 | - `data.position` - The position in which the instance will be shown. 55 | 56 | ### `defaults: {}` 57 | 58 | Any properties defined in the defaults object, will be merged with the module 59 | config as defined in the user's config.js file. This is the best place to set 60 | your modules' configuration defaults. Any of the module configuration properties 61 | can be accessed using `this.config.propertyName`, but more about that later. 62 | 63 | ### `requiresVersion:` 64 | 65 | _Introduced in version: 2.1.0._ 66 | 67 | A string that defines the minimum version of the MagicMirror framework. If it is 68 | set, the system compares the required version with the users version. If the 69 | version of the user is out of date, it won't run the module. Make sure to also 70 | set this value in the Node helper. 71 | 72 | **Note:** Since this check is introduced in version 2.1.0, this check will not 73 | be run in older versions. Keep this in mind if you get issue reports on your 74 | module. 75 | 76 | Example: 77 | 78 | ```javascript 79 | requiresVersion: "2.1.0", 80 | ``` 81 | 82 | ## Subclassable module methods 83 | 84 | ### `init()` 85 | 86 | This method is called when a module gets instantiated. In most cases you do not 87 | need to subclass this method. 88 | 89 | ### `loaded(callback)` 90 | 91 | _Introduced in version: 2.1.1._ 92 | 93 | This method is called when a module is loaded. Subsequent modules in the config 94 | are not yet loaded. The `callback` function MUST be called when the module is 95 | done loading. In most cases you do not need to subclass this method. 96 | 97 | **Example:** 98 | 99 | ```javascript 100 | loaded: function(callback) { 101 | this.finishLoading(); 102 | Log.log(this.name + ' is loaded!'); 103 | callback(); 104 | } 105 | ``` 106 | 107 | ### `start()` 108 | 109 | This method is called when all modules are loaded and the system is ready to 110 | boot up. Keep in mind that the dom object for the module is not yet created. The 111 | start method is a perfect place to define any additional module properties: 112 | 113 | **Example:** 114 | 115 | ```javascript 116 | start: function() { 117 | this.mySpecialProperty = "So much wow!"; 118 | Log.log(this.name + ' is started!'); 119 | } 120 | ``` 121 | 122 | ### `getScripts()` 123 | 124 | **Should return: Array** 125 | 126 | The getScripts method is called to request any additional scripts that need to 127 | be loaded. This method should therefore return an array with strings. If you 128 | want to return a full path to a file in the module folder, use the 129 | `this.file('filename.js')` method. In all cases the loader will only load a file 130 | once. It even checks if the file is available in the default vendor folder. 131 | 132 | **Example:** 133 | 134 | ```javascript 135 | getScripts: function() { 136 | return [ 137 | 'script.js', // will try to load it from the vendor folder, otherwise it will load is from the module folder. 138 | 'moment.js', // this file is available in the vendor folder, so it doesn't need to be available in the module folder. 139 | this.file('another_file.js'), // this file will be loaded straight from the module folder. 140 | 'https://code.jquery.com/jquery-2.2.3.min.js', // this file will be loaded from the jquery servers. 141 | ] 142 | } 143 | 144 | ``` 145 | 146 | **Note:** If a file can not be loaded, the boot up of the mirror will stall. 147 | Therefore, it's advised not to use any external urls. 148 | 149 | ### `getStyles()` 150 | 151 | **Should return: Array** 152 | 153 | The getStyles method is called to request any additional stylesheets that need 154 | to be loaded. This method should therefore return an array with strings. If you 155 | want to return a full path to a file in the module folder, use the 156 | `this.file('filename.css')` method. In all cases the loader will only load a 157 | file once. It even checks if the file is available in the default vendor folder. 158 | 159 | **Example:** 160 | 161 | ```javascript 162 | getStyles: function() { 163 | return [ 164 | 'script.css', // will try to load it from the vendor folder, otherwise it will load is from the module folder. 165 | 'font-awesome.css', // this file is available in the vendor folder, so it doesn't need to be available in the module folder. 166 | this.file('another_file.css'), // this file will be loaded straight from the module folder. 167 | 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css', // this file will be loaded from the bootstrap cdn servers. 168 | ] 169 | } 170 | 171 | ``` 172 | 173 | **Note:** If a file can not be loaded, the boot up of the mirror will stall. 174 | Therefore, it's advised not to use any external URLs. 175 | 176 | ### `getTranslations()` 177 | 178 | **Should return: Dictionary** 179 | 180 | The getTranslations method is called to request translation files that need to 181 | be loaded. This method should therefore return a dictionary with the files to 182 | load, identified by the country's short name. 183 | 184 | If the module does not have any module specific translations, the function can 185 | just be omitted or return `false`. 186 | 187 | **Example:** 188 | 189 | ```javascript 190 | getTranslations: function() { 191 | return { 192 | en: "translations/en.json", 193 | de: "translations/de.json" 194 | } 195 | } 196 | 197 | ``` 198 | 199 | ### `getDom()` 200 | 201 | **Should return:** Dom Object 202 | 203 | Whenever the MagicMirror needs to update the information on screen (because it 204 | starts, or because your module asked a refresh using `this.updateDom()`), the 205 | system calls the getDom method. This method should therefore return a dom 206 | object. 207 | 208 | **Example:** 209 | 210 | ```javascript 211 | getDom: function() { 212 | const wrapper = document.createElement("div"); 213 | wrapper.innerHTML = 'Hello world!'; 214 | return wrapper; 215 | } 216 | 217 | ``` 218 | 219 | ### `getHeader()` 220 | 221 | **Should return:** String 222 | 223 | Whenever the MagicMirror needs to update the information on screen (because it 224 | starts, or because your module asked a refresh using `this.updateDom()`), the 225 | system calls the getHeader method to retrieve the module's header. This method 226 | should therefor return a string. If this method is not subclassed, this function 227 | will return the user's configured header. 228 | 229 | If you want to use the original user's configured header, reference 230 | `this.data.header`. 231 | 232 | **Note:** If the user did not configure a default header, no header will be 233 | displayed and thus this method will not be called. 234 | 235 | **Example:** 236 | 237 | ```javascript 238 | getHeader: function() { 239 | return this.data.header + ' Foo Bar'; 240 | } 241 | 242 | ``` 243 | 244 | ### `notificationReceived(notification, payload, sender)` 245 | 246 | That MagicMirror core has the ability to send notifications to modules. Or even 247 | better: the modules have the possibility to send notifications to other modules. 248 | When this module is called, it has 3 arguments: 249 | 250 | - `notification` - String - The notification identifier. 251 | - `payload` - AnyType - The payload of a notification. 252 | - `sender` - Module - The sender of the notification. If this argument is 253 | `undefined`, the sender of the notification is the core system. 254 | 255 | **Example:** 256 | 257 | ```javascript 258 | notificationReceived: function(notification, payload, sender) { 259 | if (sender) { 260 | Log.log(this.name + " received a module notification: " + notification + " from sender: " + sender.name); 261 | } else { 262 | Log.log(this.name + " received a system notification: " + notification); 263 | } 264 | } 265 | ``` 266 | 267 | **Note:** the system sends three notifications when starting up. These 268 | notifications could come in handy! 269 | 270 | - `ALL_MODULES_STARTED` - All modules are started. You can now send 271 | notifications to other modules. 272 | - `DOM_OBJECTS_CREATED` - All dom objects are created. The system is now ready 273 | to perform visual changes. 274 | - `MODULE_DOM_CREATED` - This module's dom has been fully loaded. You can now 275 | access your module's dom objects. 276 | 277 | ### `socketNotificationReceived: function(notification, payload)` 278 | 279 | When using a node_helper, the node helper can send your module notifications. 280 | When this module is called, it has 2 arguments: 281 | 282 | - `notification` - String - The notification identifier. 283 | - `payload` - AnyType - The payload of a notification. 284 | 285 | **Note 1:** When a node helper sends a notification, all modules of that module 286 | type receive the same notifications. 287 | 288 | **Note 2:** The socket connection is established as soon as the module sends its 289 | first message using 290 | [sendSocketNotification](#this-sendsocketnotification-notification-payload). 291 | 292 | **Example:** 293 | 294 | ```javascript 295 | socketNotificationReceived: function(notification, payload) { 296 | Log.log(this.name + " received a socket notification: " + notification + " - Payload: " + payload); 297 | }, 298 | ``` 299 | 300 | ### `suspend()` 301 | 302 | When a module is hidden (using the `module.hide()` method), the `suspend()` 303 | method will be called. By subclassing this method you can perform tasks like 304 | halting the update timers. 305 | 306 | ### `resume()` 307 | 308 | When a module is requested to be shown (using the `module.show()` method), the 309 | `resume()` method will be called. By subclassing this method you can perform 310 | tasks restarting the update timers. 311 | 312 | ## Module instance methods 313 | 314 | Each module instance has some handy methods which can be helpful building your 315 | module. 316 | 317 | ### `this.file(filename)` 318 | 319 | **_filename_ String** - The name of the file you want to create the path 320 | for.
**Returns String** 321 | 322 | If you want to create a path to a file in your module folder, use the `file()` 323 | method. It returns the path to the filename given as the attribute. Is method 324 | comes in handy when configuring the [getScripts](#getscripts) and 325 | [getStyles](#getstyles) methods. 326 | 327 | ### `this.updateDom(speed|options)` 328 | 329 | **_speed_ Number** - Optional. Animation speed in milliseconds.
330 | 331 | Whenever your module need to be updated, call the `updateDom(speed)` method. It 332 | requests the MagicMirror core to update its dom object. If you define the speed, 333 | the content update will be animated, but only if the content will really change. 334 | 335 | Note that the rendering of the updated dom on the screen will happen 336 | asynchronously. You can listen for the 337 | [`DOM_OBJECTS_UPDATED` notification](/development/notifications.html) to know 338 | when the rendering is complete and the new dom is safe to interact with. This 339 | notification only fires if the content will really change. 340 | 341 | As an example: the clock modules calls this method every second: 342 | 343 | ```javascript 344 | ... 345 | start: function() { 346 | let self = this; 347 | setInterval(function() { 348 | self.updateDom(); // no speed defined, so it updates instantly. 349 | }, 1000); //perform every 1000 milliseconds. 350 | }, 351 | ... 352 | ``` 353 | 354 | **_options_ Object** - (_Introduced in version: 2.25.0._) Optional. Allows you 355 | to determine the animation speed and animation type options, whenever your 356 | module needs to be updated 357 | 358 | | options | type | description | 359 | | ------- | ------ | ------------------------------------ | 360 | | speed | Number | animation speed in ms | 361 | | animate | Object | animate IN and OUT rules (see below) | 362 | 363 | **animate Object** 364 | 365 | | animate | type | description | 366 | | ------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | 367 | | in | String | Animate name when module will be shown (after dom update), it will use an `animateIn` type name (see [Animation Guide](/modules/animate#animatein)) | 368 | | out | String | Animate name when module will be hidden (before dom update), it will use an `animateOut` type name (see [Animation Guide](/modules/animate#animateout)) | 369 | 370 | As an example: 371 | 372 | ```javascript 373 | ... 374 | this.updateDom( { 375 | options: { 376 | speed: 1000, // animation duration 377 | animate: { 378 | in: "backInDown", // animation when module shown (after update) 379 | out: "backOutUp" // animation when module will hide (before update) 380 | } 381 | } 382 | }) 383 | ... 384 | ``` 385 | 386 | ### `this.sendNotification(notification, payload)` 387 | 388 | - `notification` - String - The notification identifier. 389 | - `payload` - AnyType - (Optional) A notification payload. 390 | 391 | If you want to send a notification to all other modules, use the 392 | `sendNotification(notification, payload)`. All other modules will receive the 393 | message via the 394 | [notificationReceived](#notificationreceived-notification-payload-sender) 395 | method. In that case, the sender is automatically set to the instance calling 396 | the sendNotification method. 397 | 398 | **Example:** 399 | 400 | ```javascript 401 | this.sendNotification("MY_MODULE_READY_FOR_ACTION", { foo: bar }); 402 | ``` 403 | 404 | ### `this.sendSocketNotification(notification, payload)` 405 | 406 | - `notification` - String - The notification identifier. 407 | - `payload` - AnyType - (Optional) A notification payload. 408 | 409 | If you want to send a notification to the node_helper, use the 410 | `sendSocketNotification(notification, payload)`. Only the node_helper of this 411 | module will receive the socket notification. 412 | 413 | **Example:** 414 | 415 | ```javascript 416 | this.sendSocketNotification("SET_CONFIG", this.config); 417 | ``` 418 | 419 | ### `this.hide(speed, callback, options)` 420 | 421 | **_speed_ Number** - Optional (Required when setting callback or options), The 422 | speed of the hide animation in milliseconds. 423 | 424 | **_callback_ Function** - Optional, The callback after the hide animation is 425 | finished. 426 | 427 | **_options_ Function** - Optional, Object with additional options for the hide 428 | action (see below). (_Introduced in version: 2.1.0._) 429 | 430 | To hide a module, you can call the `hide(speed, callback)` method. You can call 431 | the hide method on the module instance itself using `this.hide()`, but of course 432 | you can also hide another module using `anOtherModule.hide()`. 433 | 434 | Possible configurable options: 435 | 436 | - `lockString` - String - When setting lock string, the module can not be shown 437 | without passing the correct lock string. This way (multiple) modules can 438 | prevent a module from showing. It's considered best practice to use your 439 | modules identifier as the locksString: `this.identifier`. See _visibility 440 | locking_ below. 441 | 442 | - `animate` - String - (_Introduced in version: 2.25.0._) Hide the module with a 443 | special animate. It will use an `animateOut` type name. All animations name 444 | are available in [Animation Guide](/modules/animate.md#animateout) 445 | 446 | ::: warning Notes: 447 | 448 | - If the hide animation is cancelled, for instance because the show method is 449 | called before the hide animation was finished, the callback will not be 450 | called.
451 | - If the hide animation is hijacked (an other method calls hide on the same 452 | module),the callback will not be called.
453 | - If the dom is not yet created, the hide method won't work. Wait for the 454 | `DOM_OBJECTS_CREATED` 455 | [notification](#notificationreceived-notification-payload-sender).
456 | - If an `animateOut` is defined in global module configuration, `animate` string 457 | will be ignored 458 | 459 | ::: 460 | 461 | ### `this.show(speed, callback, options)` 462 | 463 | **_speed_ Number** - Optional (Required when setting callback or options), The 464 | speed of the show animation in milliseconds.
**_callback_ Function** - 465 | Optional, The callback after the show animation is finished.
**_options_ 466 | Function** - Optional, Object with additional options for the show action (see 467 | below). (_Introduced in version: 2.1.0._) 468 | 469 | To show a module, you can call the `show(speed, callback)` method. You can call 470 | the show method on the module instance itself using `this.show()`, but of course 471 | you can also show another module using `anOtherModule.show()`. 472 | 473 | Possible configurable options: 474 | 475 | - `lockString` - String - When setting lock string, the module can not be shown 476 | without passing the correct lock string. This way (multiple) modules can 477 | prevent a module from showing. See _visibility locking_ below. 478 | - `force` - Boolean - When setting the force tag to `true`, the locking 479 | mechanism will be overwritten. Use this option with caution. It's considered 480 | best practice to let the usage of the force option be use- configurable. See 481 | _visibility locking_ below. 482 | - `onError(error)` - Function - If a module is hidden with other lock strings 483 | and can therefore not be shown the onError callback triggers with an error 484 | object, if specified in the options (_Introduced in version: 2.15.0_). 485 | - `animate` - String - (_Introduced in version: 2.25.0._) Show the module with a 486 | special animation. It will use an `animateIn` type name. All animations name 487 | are available in [Animation Guide](/modules/animate.md#animatein) 488 | 489 | ::: warning Notes: 490 | 491 | - If the show animation is canceled, for instance because the hide method is 492 | called before the show animation was finished, the callback will not be 493 | called.
494 | - If the show animation is hijacked (an other method calls show on the same 495 | module), the callback will not be called.
496 | - If the dom is not yet created, the show method won't work. Wait for the 497 | `DOM_OBJECTS_CREATED` 498 | [notification](#notificationreceived-notification-payload-sender).
499 | - If an `animateIn` is defined in global module configuration, `animate` string 500 | will be ignored 501 | 502 | ::: 503 | 504 | ### Visibility locking 505 | 506 | (_Introduced in version: 2.1.0._) 507 | 508 | Visibility locking helps the module system to prevent unwanted hide/show 509 | actions. The following scenario explains the concept: 510 | 511 | **Module B asks module A to hide:** 512 | 513 | ```javascript 514 | moduleA.hide(0, { lockString: "module_b_identifier" }); 515 | ``` 516 | 517 | Module A is now hidden, and has an lock array with the following strings: 518 | 519 | ```javascript 520 | moduleA.lockStrings == ["module_b_identifier"]; 521 | moduleA.hidden == true; 522 | ``` 523 | 524 | **Module C asks module A to hide:** 525 | 526 | ```javascript 527 | moduleA.hide(0, { lockString: "module_c_identifier" }); 528 | ``` 529 | 530 | Module A is now hidden, and has an lock array with the following strings: 531 | 532 | ```javascript 533 | moduleA.lockStrings == ["module_b_identifier", "module_c_identifier"]; 534 | moduleA.hidden == true; 535 | ``` 536 | 537 | **Module B asks module A to show:** 538 | 539 | ```javascript 540 | moduleA.show(0, { lockString: "module_b_identifier" }); 541 | ``` 542 | 543 | The lockString will be removed from moduleA’s locks array, but since there still 544 | is an other lock string available, the module remains hidden: 545 | 546 | ```javascript 547 | moduleA.lockStrings == ["module_c_identifier"]; 548 | moduleA.hidden == true; 549 | ``` 550 | 551 | **Module C asks module A to show:** 552 | 553 | ```javascript 554 | moduleA.show(0, { lockString: "module_c_identifier" }); 555 | ``` 556 | 557 | The lockString will be removed from moduleA’s locks array, and since this will 558 | result in an empty lock array, the module will be visible: 559 | 560 | ```javascript 561 | moduleA.lockStrings == []; 562 | moduleA.hidden == false; 563 | ``` 564 | 565 | **Note:** The locking mechanism can be overwritten by using the force tag: 566 | 567 | ```javascript 568 | moduleA.show(0, { force: true }); 569 | ``` 570 | 571 | This will reset the lockStrings array, and will show the module. 572 | 573 | ```javascript 574 | moduleA.lockStrings == []; 575 | moduleA.hidden == false; 576 | ``` 577 | 578 | Use this `force` method with caution. See `show()` method for more information. 579 | 580 | ### `this.translate(identifier)` 581 | 582 | **_identifier_ String** - Identifier of the string that should be translated. 583 | 584 | MagicMirror contains a convenience wrapper for `l18n`. You can use this to 585 | automatically serve different translations for your modules based on the user's 586 | `language` configuration. 587 | 588 | If no translation is found, a fallback will be used. The fallback sequence is as 589 | follows: 590 | 591 | - 1. Translation as defined in module translation file of the user's preferred 592 | language. 593 | - 2. Translation as defined in core translation file of the user's preferred 594 | language. 595 | - 3. Translation as defined in module translation file of the fallback language 596 | (the first defined module translation file). 597 | - 4. Translation as defined in core translation file of the fallback language 598 | (the first defined core translation file). 599 | - 5. The key (identifier) of the translation. 600 | 601 | When adding translations to your module, it's a good idea to see if an 602 | appropriate translation is already available in the 603 | [core translation files](https://github.com/MagicMirrorOrg/MagicMirror/tree/master/translations). 604 | This way, your module can benefit from the existing translations. 605 | 606 | **Example:** 607 | 608 | ```javascript 609 | this.translate("INFO"); //Will return a translated string for the identifier INFO 610 | ``` 611 | 612 | **Example json file:** 613 | 614 | ```javascript 615 | { 616 | "INFO": "Really important information!" 617 | } 618 | ``` 619 | 620 | **Note:** although comments are officially not supported in JSON files, 621 | MagicMirror allows it by stripping the comments before parsing the JSON file. 622 | Comments in translation files could help other translators. 623 | 624 | #### `this.translate(identifier, variables)` 625 | 626 | **_identifier_ String** - Identifier of the string that should be 627 | translated.
**_variables_ Object** - Object of variables to be used in 628 | translation. 629 | 630 | This improved and backwards compatible way to handle translations behaves like 631 | the normal translation function and follows the rules described above. It's 632 | recommended to use this new format for translating everywhere. It allows 633 | translator to change the word order in the sentence to be translated. 634 | 635 | **Example:** 636 | 637 | ```javascript 638 | const timeUntilEnd = moment(event.endDate, "x").fromNow(true); 639 | this.translate("RUNNING", { "timeUntilEnd": timeUntilEnd) }); // Will return a translated string for the identifier RUNNING, replacing `{timeUntilEnd}` with the contents of the variable `timeUntilEnd` in the order that translator intended. 640 | ``` 641 | 642 | **Example English.json file:** 643 | 644 | ```javascript 645 | { 646 | "RUNNING": "Ends in {timeUntilEnd}", 647 | } 648 | ``` 649 | 650 | **Example Finnish.json file:** 651 | 652 | ```javascript 653 | { 654 | "RUNNING": "Päättyy {timeUntilEnd} päästä", 655 | } 656 | ``` 657 | 658 | **Note:** The _variables_ Object has an special case called `fallback`. It's 659 | used to support old translations in translation files that do not have the 660 | variables in them. If you are upgrading an old module that had translations that 661 | did not support the word order, it is recommended to have the fallback layout. 662 | 663 | **Example:** 664 | 665 | ```javascript 666 | const timeUntilEnd = moment(event.endDate, "x").fromNow(true); 667 | this.translate("RUNNING", { 668 | "fallback": this.translate("RUNNING") + " {timeUntilEnd}" 669 | "timeUntilEnd": timeUntilEnd 670 | )}); // Will return a translated string for the identifier RUNNING, replacing `{timeUntilEnd}` with the contents of the variable `timeUntilEnd` in the order that translator intended. (has a fallback) 671 | ``` 672 | 673 | **Example Swedish.json file that does not have the variable in it:** 674 | 675 | ```javascript 676 | { 677 | "RUNNING": "Slutar", 678 | } 679 | ``` 680 | 681 | In this case the `translate`-function will not find any variables in the 682 | translation, will look for `fallback` variable and use that if possible to 683 | create the translation. 684 | -------------------------------------------------------------------------------- /development/documentation.md: -------------------------------------------------------------------------------- 1 | # How to write good documentation 2 | 3 | MagicMirror is meant to be accessible to anyone with any skill level. But to 4 | help promote building technical skills and educate in these technologies, it 5 | requires a little more effort from developers to make their amazing projects 6 | more easily obtainable by ordinary people. 7 | 8 | Most novices coming to MM are overwhelmed by the amount of information and 9 | perhaps even the technology itself. To overcome this obstacle, they need a lot 10 | of help in getting things going. As with anything we learn in life, we take it 11 | one step at the time. 12 | 13 | Here is a guideline for writing a non-technical installation documentation to 14 | help people use your creation. 15 | 16 | It's in no way meant to be exhaustive, but it will try to make sure to relieve 17 | your github issues from excessive novice questions and in addition makes it much 18 | easier to post good and useful answers. 19 | 20 | ### The most important points in writing software installation documentation: 21 | 22 | - **Don't assume any previous knowledge!** This is by far, the number one 23 | documentation issue and failure! 24 | - **Does the software depend on any other, previously installed software?** 25 | - If so make sure to either re-iterate the steps or link to equivalently good 26 | installation instructions. 27 | - Specify exactly what it depends on, and where to find it. 28 | - **Are the steps following a logical order of operations?** 29 | You'll be surprised! 30 | - **Is the information you give correct?** 31 | Don't guess how things work! 32 | - **Are all the steps up-to-date with current master repository code and 33 | functionality?** 34 | This is the hardest to keep up, since most projects in github are constantly 35 | under development. 36 | - **Are your screenshots up-to-date with how the UI actually looks?** 37 | You have screenshots, right!? A million of your words could never replace 38 | them. 39 | - **Have you started from scratch and followed your own installation 40 | instructions?** 41 | This step is what fails 99.9% of all documentation. Unfortunately developers 42 | are incredibly lazy in this regard, since they think it's a waste of time. I'm 43 | sure NASA has something to teach you about this. 44 | - **Can anyone complete the steps successfully?** 45 | Can your 9 year old baby sister or grandma follow the steps without asking for 46 | help? 47 | - **Can anyone raise a question in the github issues?** 48 | - Are you going to answer respectfully, short and concise and point the user 49 | to where to find the information, and take into consideration that perhaps 50 | something is not clear from your documentation and needs more attention. 51 | (Perhaps the UI, a dependency or link has changed?) 52 | - Or are you going to be a cocky ass and give degrading comments? 53 | 54 | --- 55 | 56 | ### And always remember: IF YOU WRITE IT GOOD, THEY WILL COME! 57 | -------------------------------------------------------------------------------- /development/helper-methods.md: -------------------------------------------------------------------------------- 1 | # MagicMirror Helper Methods 2 | 3 | The MagicMirror core object `MM` has some handy methods to help you control your 4 | and other modules. Most of the `MM` methods are available via the convenience 5 | methods on the Module instance. 6 | 7 | ## Module selection 8 | 9 | The only additional method available for your module, is the feature to retrieve 10 | references to other modules. This can be used to hide and show other modules. 11 | 12 | ### `MM.getModules()` 13 | 14 | **Returns Array** - An array with module instances. 15 | 16 | To make a selection of all currently loaded module instances, run the 17 | `MM.getModules()` method. It will return an array with all currently loaded 18 | module instances. The returned array has a lot of filtering methods. See below 19 | for more info. 20 | 21 | **Note:** This method returns an empty array if not all modules are started yet. 22 | Wait for the `ALL_MODULES_STARTED` 23 | [notification](core-module-file.md#notificationreceived-notification-payload-sender). 24 | 25 | #### `.withClass(classnames)` 26 | 27 | **_classnames_ String or Array** - The class names on which you want to filter. 28 | **Returns Array** - An array with module instances. 29 | 30 | If you want to make a selection based on one or more class names, use the 31 | withClass method on a result of the `MM.getModules()` method. The argument of 32 | the `withClass(classname)` method can be an array, or space separated string. 33 | 34 | **Examples:** 35 | 36 | ```javascript 37 | let modules = MM.getModules().withClass("classname"); 38 | let modules = MM.getModules().withClass("classname1 classname2"); 39 | let modules = MM.getModules().withClass(["classname1", "classname2"]); 40 | ``` 41 | 42 | #### `.exceptWithClass(classnames)` 43 | 44 | **_classnames_ String or Array** - The class names of the modules you want to 45 | remove from the results. **Returns Array** - An array with module instances. 46 | 47 | If you to remove some modules from a selection based on a classname, use the 48 | exceptWithClass method on a result of the `MM.getModules()` method. The argument 49 | of the `exceptWithClass(classname)` method can be an array, or space separated 50 | string. 51 | 52 | **Examples:** 53 | 54 | ```javascript 55 | let modules = MM.getModules().exceptWithClass("classname"); 56 | let modules = MM.getModules().exceptWithClass("classname1 classname2"); 57 | let modules = MM.getModules().exceptWithClass(["classname1", "classname2"]); 58 | ``` 59 | 60 | #### `.exceptModule(module)` 61 | 62 | **_module_ Module Object** - The reference to a module you want to remove from 63 | the results. **Returns Array** - An array with module instances. 64 | 65 | If you to remove a specific module instance from a selection based on a 66 | classname, use the exceptWithClass method on a result of the `MM.getModules()` 67 | method. This can be helpful if you want to select all module instances except 68 | the instance of your module. 69 | 70 | **Examples:** 71 | 72 | ```javascript 73 | let modules = MM.getModules().exceptModule(this); 74 | ``` 75 | 76 | Of course, you can combine all of the above filters: 77 | 78 | **Example:** 79 | 80 | ```javascript 81 | let modules = MM.getModules() 82 | .withClass("classname1") 83 | .exceptWithClass("classname2") 84 | .exceptModule(aModule); 85 | ``` 86 | 87 | #### `.enumerate(callback)` 88 | 89 | **_callback_ Function(module)** - The callback run on every instance. 90 | 91 | If you want to perform an action on all selected modules, you can use the 92 | `enumerate` function: 93 | 94 | ```javascript 95 | MM.getModules().enumerate(function (module) { 96 | Log.log(module.name); 97 | }); 98 | ``` 99 | 100 | **Example:** To hide all modules except your module instance, you could write 101 | something like: 102 | 103 | ```javascript 104 | Module.register("modulename", { 105 | //... 106 | notificationReceived: function (notification, payload, sender) { 107 | if (notification === "DOM_OBJECTS_CREATED") { 108 | MM.getModules() 109 | .exceptModule(this) 110 | .enumerate(function (module) { 111 | module.hide(1000, function () { 112 | //Module hidden. 113 | }); 114 | }); 115 | } 116 | }, 117 | //... 118 | }); 119 | ``` 120 | -------------------------------------------------------------------------------- /development/introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Introduction 3 | --- 4 | 5 | # Module Development Documentation 6 | 7 | This documentation describes the way to develop your own MagicMirror² modules. 8 | 9 | ## General Advice 10 | 11 | As MagicMirror² has gained huge popularity, so has the number of available 12 | modules. For new users and developers alike, it is very time-consuming to 13 | navigate around the various repositories in order to find out what exactly a 14 | certain modules does, how it looks and what it depends on. Unfortunately, this 15 | information is rarely available, nor easily obtained without having to install 16 | it first. Therefore, **we highly recommend you to include the following 17 | information in your README file.** 18 | 19 | - A high quality screenshot of your working module 20 | - A short, one sentence, clear description what it does (duh!) 21 | - What external API's it depends upon, including web links to those 22 | - Whether the API/request require a key and the user limitations of those. (Is 23 | it free?) 24 | 25 | Surely this also help you get better recognition and feedback for your work. 26 | 27 | ## Module name 28 | 29 | We recommend the following pattern: `MMM-MyNewCoolModule`. But it is not 30 | mandatory - your module will also work with other name patterns (as long as no 31 | other module has the same name). 32 | 33 | ## Quick start 34 | 35 | To rocket launch your module, you can use the 36 | [MMM-Template](https://github.com/Dennis-Rosenbaum/MMM-Template) or immediately 37 | [MMM-Template](https://github.com/new?template_name=MMM-Template&template_owner=Dennis-Rosenbaum). 38 | Please read the 39 | [MMM-Template wiki](https://github.com/Dennis-Rosenbaum/MMM-Template/wiki) for 40 | more information. 41 | 42 | **Please note!** This module is an externally developed module and not 43 | maintained by the MagicMirrorOrg. 44 | 45 | ## Module structure 46 | 47 | All modules are loaded in the `modules` folder. The default modules are grouped 48 | together in the `modules/default` folder. Your module should be placed in a 49 | subfolder of `modules`. Note that any file or folder you create in the `modules` 50 | folder will be ignored by git, allowing you to upgrade the MagicMirror² without 51 | the loss of your files. 52 | 53 | A module can be placed in one single folder. Or multiple modules can be grouped 54 | in a subfolder. Note that name of the module must be unique. Even when a module 55 | with a similar name is placed in a different folder, they can't be loaded at the 56 | same time. 57 | 58 | ### Files 59 | 60 | - **modulename/modulename.js** - This is your core module script. 61 | - **modulename/node_helper.js** - This is an optional helper that will be loaded 62 | by the node script. The node helper and module script can communicate with 63 | each other using an integrated socket system. 64 | - **modulename/public** - Any files in this folder can be accessed via the 65 | browser on `/modulename/filename.ext`. 66 | - **modulename/anyfileorfolder** Any other file or folder in the module folder 67 | can be used by the core module script. For example: 68 | _modulename/css/modulename.css_ would be a good path for your additional 69 | module styles. 70 | -------------------------------------------------------------------------------- /development/logger.md: -------------------------------------------------------------------------------- 1 | # Logger 2 | 3 | The MagicMirror contains a convenience wrapper for logging. Currently, this 4 | logger is a simple proxy to the original `console.log` methods. But it might get 5 | additional features in the future. 6 | 7 | **Examples:** 8 | 9 | ```javascript 10 | Log.info("info"); 11 | Log.log("log"); 12 | Log.error("error"); 13 | ``` 14 | 15 | By default, the logger is only available in the core module file. If you want to 16 | use the logger in the `node_helper.js`, you have to add it by inserting the 17 | following line at the beginning of the file: 18 | 19 | ```javascript 20 | const Log = require("logger"); 21 | ``` 22 | 23 | Remember: Much of the JavaScript code is run in the electron front-end or 24 | browser, so check the those consoles for log output as well. 25 | -------------------------------------------------------------------------------- /development/node-helper.md: -------------------------------------------------------------------------------- 1 | # The Node Helper 2 | 3 | The node helper (`node_helper.js`) is a Node.js script that is able to do some 4 | backend task to support your module. For every module type, only one node helper 5 | instance will be created. For example: if your MagicMirror uses two calendar 6 | modules, there will be only one calendar node helper instantiated. 7 | 8 | **Note:** Because there is only one node helper per module type, there is no 9 | default config available within your module. It's your task to send the desired 10 | config from your module to your node helper. 11 | 12 | In its most simple form, the node_helper.js file must contain: 13 | 14 | ```javascript 15 | const NodeHelper = require("node_helper"); 16 | module.exports = NodeHelper.create({}); 17 | ``` 18 | 19 | Of course, the above helper would not do anything useful. So with the 20 | information above, you should be able to make it a bit more sophisticated. 21 | 22 | ## Available module instance properties 23 | 24 | ### `this.name` 25 | 26 | **String** 27 | 28 | The name of the module 29 | 30 | ### `this.path` 31 | 32 | **String** 33 | 34 | The path of the module 35 | 36 | ### `this.expressApp` 37 | 38 | **Express App Instance** 39 | 40 | This is a link to the express instance. It will allow you to define extra 41 | routes. 42 | 43 | **Example:** 44 | 45 | ```javascript 46 | start: function() { 47 | this.expressApp.get("/foobar", function (req, res) { 48 | res.send("GET request to /foobar"); 49 | }); 50 | } 51 | ``` 52 | 53 | **Note:** By default, a public path to your module's public folder will be 54 | created: 55 | 56 | ```javascript 57 | this.expressApp.use("/" + this.name, express.static(this.path + "/public")); 58 | ``` 59 | 60 | ### `this.io` 61 | 62 | **Socket IO Instance** 63 | 64 | This is a link to the IO instance. It will allow you to do some Socket.IO magic. 65 | In most cases you won't need this, since the Node Helper has a few convenience 66 | methods to make this simple. 67 | 68 | ### `requiresVersion:` 69 | 70 | _Introduced in version: 2.1.0._ 71 | 72 | A string that defines the minimum version of the MagicMirror framework. If it is 73 | set, the system compares the required version with the users version. If the 74 | version of the user is out of date, it won't run the module. 75 | 76 | **Note:** Since this check is introduced in version 2.1.0, this check will not 77 | be run in older versions. Keep this in mind if you get issue reports on your 78 | module. 79 | 80 | Example: 81 | 82 | ```javascript 83 | requiresVersion: "2.1.0", 84 | ``` 85 | 86 | ## Subclassable module methods 87 | 88 | ### `init()` 89 | 90 | This method is called when a node helper gets instantiated. In most cases you do 91 | not need to subclass this method. 92 | 93 | ### `start()` 94 | 95 | This method is called when all node helpers are loaded and the system is ready 96 | to boot up. The start method is a perfect place to define any additional module 97 | properties: 98 | 99 | **Example:** 100 | 101 | ```javascript 102 | start: function() { 103 | this.mySpecialProperty = "So much wow!"; 104 | Log.log(this.name + " is started!"); 105 | } 106 | ``` 107 | 108 | ### `stop()` 109 | 110 | This method is called when the MagicMirror server receives a `SIGINT` command 111 | and is shutting down. This method should include any commands needed to close 112 | any open connections, stop any sub-processes and gracefully exit the module. 113 | 114 | **Example:** 115 | 116 | ```javascript 117 | stop: function() { 118 | Log.log("Shutting down MyModule"); 119 | this.connection.close(); 120 | } 121 | ``` 122 | 123 | ### `socketNotificationReceived: function(notification, payload)` 124 | 125 | With this method, your node helper can receive notifications from your modules. 126 | When this method is called, it has 2 arguments: 127 | 128 | - `notification` - String - The notification identifier. 129 | - `payload` - AnyType - The payload of a notification. 130 | 131 | **Note:** The socket connection is established as soon as the module sends its 132 | first message using 133 | [sendSocketNotification](core-module-file.md#this-sendsocketnotification-notification-payload). 134 | 135 | **Example:** 136 | 137 | ```javascript 138 | socketNotificationReceived: function(notification, payload) { 139 | Log.log(this.name + " received a socket notification: " + notification + " - Payload: " + payload); 140 | }, 141 | ``` 142 | 143 | ## Module instance methods 144 | 145 | Each node helper has some handy methods which can be helpful building your 146 | module. 147 | 148 | ### `this.sendSocketNotification(notification, payload)` 149 | 150 | - `notification` - String - The notification identifier. 151 | - `payload` - AnyType - (Optional) The payload of a notification. 152 | 153 | If you want to send a notification to your module, use the 154 | `sendSocketNotification(notification, payload)`. Only the module of your module 155 | type will receive the socket notification. 156 | 157 | **Note:** Since all instances of your module will receive the notifications, 158 | it's your task to make sure the right module responds to your messages. 159 | 160 | **Example:** 161 | 162 | ```javascript 163 | this.sendSocketNotification("SET_CONFIG", this.config); 164 | ``` 165 | 166 | ::: warning Reminder 167 | 168 | `sendSocketNotification` sends a notification from the helper to all the 169 | instances of your module. 170 | 171 | ::: 172 | 173 | ## Using native node modules in your node_helper 174 | 175 | If you want use `native node modules` within electron you need to recompile them 176 | for electron. To do so you have to install `electron-rebuild`. 177 | 178 | ```shell 179 | npm install --save-dev @electron/rebuild 180 | ``` 181 | 182 | and run it after every install (package.json example): 183 | 184 | ```javascript 185 | ... 186 | "scripts": { 187 | ... 188 | "postinstall": "./node_modules/.bin/electron-rebuild" 189 | } 190 | ... 191 | ``` 192 | -------------------------------------------------------------------------------- /development/notifications.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Notifications 3 | --- 4 | 5 | # Introduction 6 | 7 | The MagicMirror core has the ability to send notifications to modules. Or even 8 | better: the modules have the possibility to send notifications to other modules. 9 | 10 | Additional technical information on the notifications can be found in the 11 | [modules' documentation](/development/introduction.md#general-advice): 12 | 13 | - [notificationReceived](/development/core-module-file.md#subclassable-module-methods) 14 | - [sendNotification](/development/core-module-file.md#module-instance-methods) 15 | 16 | # System notifications 17 | 18 | The system sends three notifications when starting up: 19 | 20 | | Notification | Payload | Description | 21 | | --------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 22 | | `ALL_MODULES_STARTED` | _none_ | All modules are started. You can now send notifications to other modules. | 23 | | `DOM_OBJECTS_CREATED` | _none_ | All dom objects are created. The system is now ready to perform visual changes. | 24 | | `MODULE_DOM_CREATED` | _none_ | This module's dom has been fully loaded. You can now access your module's dom objects. | 25 | | `MODULE_DOM_UPDATED` | _none_ | This module's dom has been updated and re-rendered. You can now access your module's (updated) dom objects. This notification is sent in response to a call to [`updateDom`](https://docs.magicmirror.builders/development/core-module-file.html#module-instance-methods). | 26 | 27 | # Default module notifications 28 | 29 | These notifications are sent by the default modules: 30 | 31 | | Notification | Payload | Description | 32 | | ---------------------- | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 33 | | `SHOW_ALERT` | [message details](https://github.com/MagicMirrorOrg/MagicMirror/tree/master/modules/default/alert#notification-params) | Sent to [alert module](https://github.com/MagicMirrorOrg/MagicMirror/tree/master/modules/default/alert) to show an alert or notification. | 34 | | `HIDE_ALERT` | _none_ | Sent to [alert module](https://github.com/MagicMirrorOrg/MagicMirror/tree/master/modules/default/alert) to hide the current alert or notification. | 35 | | `CALENDAR_EVENTS` | [calendar events](https://github.com/MagicMirrorOrg/MagicMirror/tree/master/modules/default/calendar) | Sent by [calendar module](https://github.com/MagicMirrorOrg/MagicMirror/tree/master/modules/default/calendar) to inform modules of the calendar events. | 36 | | `ARTICLE_NEXT` | _none_ | Shows the next news title in [newsfeed module](https://github.com/MagicMirrorOrg/MagicMirror/tree/master/modules/default/newsfeed). | 37 | | `ARTICLE_PREVIOUS` | _none_ | Shows the previous news title in [newsfeed module](https://github.com/MagicMirrorOrg/MagicMirror/tree/master/modules/default/newsfeed). | 38 | | `ARTICLE_MORE_DETAILS` | _none_ | Shows more details in [newsfeed module](https://github.com/MagicMirrorOrg/MagicMirror/tree/master/modules/default/newsfeed). | 39 | | `ARTICLE_LESS_DETAILS` | _none_ | Hides the summary or full news article and only displays the news title of the currently viewed news item in [newsfeed module](https://github.com/MagicMirrorOrg/MagicMirror/tree/master/modules/default/newsfeed). | 40 | | `ARTICLE_TOGGLE_FULL` | _none_ | Toggles article in fullscreen in [newsfeed module](https://github.com/MagicMirrorOrg/MagicMirror/tree/master/modules/default/newsfeed). | 41 | 42 | # 3rd Party Module notifications 43 | 44 | Take a look in the [wiki](https://github.com/MagicMirrorOrg/MagicMirror/wiki/) 45 | to see if 3rd party modules send notifications you might want to use. 46 | -------------------------------------------------------------------------------- /development/weather-provider.md: -------------------------------------------------------------------------------- 1 | # Weather Module Weather Provider Development 2 | 3 | This document describes the way to develop your own MagicMirror² weather 4 | provider for the weather module. 5 | 6 | ## The weather provider file: yourprovider.js 7 | 8 | This is the script in which the weather provider will be defined. In its most 9 | simple form, the weather provider must implement the following: 10 | 11 | ```javascript 12 | WeatherProvider.register("yourprovider", { 13 | providerName: "YourProvider", 14 | 15 | fetchCurrentWeather() {}, 16 | 17 | fetchWeatherForecast() {}, 18 | }); 19 | ``` 20 | 21 | ## Weather provider methods to implement 22 | 23 | ::: warning IMPORTANT 24 | 25 | The weather module expects the weather data to be in metric units: 26 | 27 | - `degree celsius` for temperatures 28 | - `meters per second` for wind 29 | 30 | Some weather APIs already deliver their data in those units. 31 | 32 | If that is not the case you can use helper methods from the `weatherutils.js` 33 | class to convert the data. 34 | 35 | ::: 36 | 37 | ### `fetchCurrentWeather()` 38 | 39 | This method is called when the weather module tries to fetch the current weather 40 | of your provider. The implementation of this method is required for current 41 | weather support. The implementation can make use of the already implemented 42 | function `this.fetchData(url, method, data);`, which is returning a promise. 43 | After the response is processed, the current weather information (as a 44 | [WeatherObject](#weatherobject)) needs to be set with 45 | `this.setCurrentWeather(currentWeather);`. It will then automatically refresh 46 | the module DOM with the new data. 47 | 48 | ### `fetchWeatherForecast()` 49 | 50 | This method is called when the weather module tries to fetch the weather of your 51 | provider. The implementation of this method is required for forecast support. 52 | The implementation can make use of the already implemented function 53 | `this.fetchData(url, method, data);`, which is returning a promise. After the 54 | response is processed, the weather forecast information (as an array of 55 | [WeatherObject](#weatherobject)s) needs to be set with 56 | `this.setWeatherForecast(forecast);`. It will then automatically refresh the 57 | module DOM with the new data. 58 | 59 | ### `fetchWeatherHourly()` 60 | 61 | This method is called when the weather module tries to fetch the weather of your 62 | provider. The implementation of this method is required for hourly support. The 63 | implementation can make use of the already implemented function 64 | `this.fetchData(url, method, data);`, which is returning a promise. After the 65 | response is processed, the hourly weather forecast information (as an array of 66 | [WeatherObject](#weatherobject)s) needs to be set with 67 | `this.setWeatherHourly(forecast);`. It will then automatically refresh the 68 | module DOM with the new data. 69 | 70 | ## Weather Provider instance methods 71 | 72 | ### `init()` 73 | 74 | Called when a weather provider is initialized. 75 | 76 | ### `setConfig(config)` 77 | 78 | Called to set the config, this config is the same as the weather module's 79 | config. 80 | 81 | ### `start()` 82 | 83 | Called when the weather provider is about to start. 84 | 85 | #### `currentWeather()` 86 | 87 | This returns a WeatherDay object for the current weather. 88 | 89 | ### `weatherForecast()` 90 | 91 | This returns an array of WeatherDay objects for the weather forecast. 92 | 93 | ### `weatherHourly()` 94 | 95 | This returns an array of WeatherDay objects for the hourly weather forecast. 96 | 97 | ### `fetchedLocation()` 98 | 99 | This returns the name of the fetched location or an empty string. 100 | 101 | ### `setCurrentWeather(currentWeatherObject)` 102 | 103 | Set the currentWeather and notify the delegate that new information is 104 | available. 105 | 106 | ### `setWeatherForecast(weatherForecastArray)` 107 | 108 | Set the weatherForecastArray and notify the delegate that new information is 109 | available. 110 | 111 | ### `setWeatherHourly(weatherHourlyArray)` 112 | 113 | Set the weatherHourlyArray and notify the delegate that new information is 114 | available. 115 | 116 | ### `setFetchedLocation(name)` 117 | 118 | Set the fetched location name. 119 | 120 | ### `updateAvailable()` 121 | 122 | Notify the delegate that new weather is available. 123 | 124 | ### `fetchData(url, method, data)` 125 | 126 | A convenience function to make requests. It returns a promise. 127 | 128 | ## WeatherObject 129 | 130 | This object holds all data from your provider for usage in the template. 131 | 132 | | Property | Type | Value/Unit | 133 | | -------------- | -------- | --------------------------------------------------------------------------------------------------------------- | 134 | | date | `object` | [Moment.js](https://momentjs.com/) object of the time/date. | 135 | | windSpeed | `number` | Speed of the wind in metric: `meter/second` | 136 | | windDirection | `number` | Direction of the wind in degrees. | 137 | | sunrise | `object` | [Moment.js](https://momentjs.com/) object of sunrise. | 138 | | sunset | `object` | [Moment.js](https://momentjs.com/) object of sunset. | 139 | | temperature | `number` | Current temperature in metric `celsius degree`. | 140 | | minTemperature | `number` | Lowest temperature of the day in metric `celsius degree`. | 141 | | maxTemperature | `number` | Highest temperature of the day in metric `celsius degree`. | 142 | | weatherType | `string` | Icon name of the weather type.
Possible values: [WeatherIcons](https://www.npmjs.com/package/weathericons) | 143 | | humidity | `number` | Percentage of humidity | 144 | | rain | `number` | Metric: `millimeters`
Imperial: `inches` | 145 | | snow | `number` | Metric: `millimeters`
Imperial: `inches` | 146 | | precipitation | `number` | Metric: `millimeters`
Imperial: `inches`
UK Met Office provider: `percent` | 147 | 148 | ### Current weather 149 | 150 | For the current weather object the following properties are required: 151 | 152 | - humidity 153 | - sunrise 154 | - sunset 155 | - temperature 156 | - weatherType 157 | - windDirection 158 | - windSpeed 159 | 160 | ### Weather forecast 161 | 162 | For the forecast weather object the following properties are required: 163 | 164 | - date 165 | - maxTemperature 166 | - minTemperature 167 | - rain 168 | - weatherType 169 | -------------------------------------------------------------------------------- /getting-started/installation.md: -------------------------------------------------------------------------------- 1 | # Installation & Usage 2 | 3 | The MagicMirror² can be installed manually or using automatic installers. At the 4 | start of 2020 the decision was made to remove the automatic installer from the 5 | MagicMirror² core repository and move it to a community maintained separate 6 | repository. For more information about this decision, please check issue 7 | [#1860](https://github.com/MagicMirrorOrg/MagicMirror/issues/1860) on GitHub. 8 | 9 | Therefore the only officially supported way of installation is by using a 10 | [manual installation](#manual-installation). Using external installation scripts 11 | is at your own risk but can make the process a lot easier. Available automatic 12 | installers can be found under: 13 | [alternative installation methods](#alternative-installation-methods). 14 | 15 | ## Manual Installation 16 | 17 | 1. Download and install a 18 | [required](https://github.com/MagicMirrorOrg/MagicMirror/releases) _Node.js_ 19 | version, see the official documentation: 20 | - [Linux based distributions](https://github.com/nodesource/distributions) 21 | - [Others](https://nodejs.org/en/download) 22 | 2. check if `git` is installed on your machine by executing `git` (should show 23 | usage), otherwise install it 24 | 3. Clone the repository: 25 | `git clone https://github.com/MagicMirrorOrg/MagicMirror` 26 | 4. Enter the repository: `cd MagicMirror` 27 | 5. Install the application: `npm run install-mm` 28 | 6. Make a copy of the config sample file: 29 | `cp config/config.js.sample config/config.js` 30 | 7. Start the application: `npm run start` \ 31 | For **Server Only** use: `npm run server` 32 | 33 | ::: warning NOTE 34 | 35 | The installation step for `npm run install-mm` will take a very long time, often 36 | with little or no terminal response! For the RPi3 this is **~10** minutes and 37 | for the Rpi2 **~25** minutes. Do not interrupt or you risk getting a 38 | :broken_heart: by Raspberry Jam. 39 | 40 | ::: 41 | 42 | ## Alternative Installation Methods 43 | 44 | The following installation methods are not maintained by the MagicMirror² core 45 | team. Use these scripts and methods at your own risk. 46 | 47 | ### Automatic Installation Scripts 48 | 49 | - Sam (@sdetweil, long time contributor of the MagicMirror² framework) maintains 50 | an easy-to-use installation and update script: 51 | [https://github.com/sdetweil/MagicMirror_scripts](https://github.com/sdetweil/MagicMirror_scripts) 52 | - [The MagicMirror Package Manager](https://github.com/Bee-Mar/mmpm) is a 53 | command line interface designed to simplify the installation, removal, and 54 | maintenance of MagicMirror modules. 55 | 56 | ### Docker Image 57 | 58 | - MagicMirror² can be deployed using [Docker](https://docker.com). Head over to 59 | [this repository](https://gitlab.com/khassel/magicmirror) for more 60 | information. 61 | 62 | ### Kubernetes Helm Chart 63 | 64 | - If you want to run MagicMirror² (in server only mode) in a kubernetes cluster 65 | then take a look at this 66 | [MagicMirror Helm Chart](https://gitlab.com/khassel/magicmirror-helm). 67 | 68 | ### MagicMirrorOS 69 | 70 | - This is a full OS based on Raspberry Pi OS. So instead of downloading 71 | Raspberry Pi OS and putting this on your sd card, you can use 72 | [MagicMirrorOS](https://github.com/guysoft/MagicMirrorOS) instead. It runs out 73 | of the box with a default setup of MagicMirror, under the hood it uses the 74 | [docker setup](https://gitlab.com/khassel/magicmirror). 75 | 76 | ### NPM 77 | 78 | - We also publish the latest version of MagicMirror to the 79 | [npm-registry](https://www.npmjs.com/package/magicmirror). 80 | 81 | ## Other Operating Systems 82 | 83 | ### Windows 84 | 85 | ::: warning IMPORTANT 86 | 87 | MagicMirror² is designed to run on Linux. But with an extra step in the 88 | installation process and a different start command, you can also run it on 89 | Windows. Some third-party modules may not work on Windows. 90 | 91 | ::: 92 | 93 | To get the software running on Windows, you have to do two things in addition to 94 | the [steps](#manual-installation) above: 95 | 96 | **After step 5:** Install dependencies in the vendor and font directories: 97 | 98 | Powershell: 99 | 100 | 1. `cd fonts; npm install; cd ..` 101 | 2. `cd vendor; npm install; cd ..` 102 | 103 | Command Prompt: 104 | 105 | 1. `cd fonts && npm install && cd ..` 106 | 2. `cd vendor && npm install && cd ..` 107 | 108 | Otherwise the screen will stay black when starting the software. 109 | 110 | **Step 7:** In Windows you must use `npm run start:windows` instead of 111 | `npm run start`. 112 | 113 | ## Usage 114 | 115 | Note the following: 116 | 117 | - `npm run start` does **not** work via SSH. But you can use 118 | `DISPLAY=:0 nohup npm run start &` instead. \ 119 | This starts the mirror on the remote display. 120 | - If you want to debug on your Raspberry Pi you can use `npm run start:dev` 121 | which will start MM with _Dev Tools_ enabled. 122 | - To access the toolbar menu when in mirror mode, hit `ALT` key. 123 | - To toggle the (web) `Developer Tools` from mirror mode, use `CTRL-SHIFT-I` or 124 | `ALT` and select `View`. 125 | 126 | ### Server Only 127 | 128 | In some cases, you want to start the application without an actual app window. 129 | In this case, you can start MagicMirror² in server only mode by manually running 130 | `npm run server`. This will start the server, after which you can open the 131 | application in your browser of choice. Detailed description below. 132 | 133 | ::: warning IMPORTANT 134 | 135 | Make sure that you whitelist the interface/ip (`ipWhitelist`) in the server 136 | config where you want the client to connect to, otherwise it will not be allowed 137 | to connect to the server. You also need to set the local host `address` field to 138 | `0.0.0.0` in order for the RPi to listen on all interfaces and not only 139 | `localhost` (default). 140 | 141 | ::: 142 | 143 | ```javascript 144 | let config = { 145 | address: "0.0.0.0", // default is "localhost" 146 | port: 8080, // default 147 | ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:172.17.0.1"], // default -- need to add your IP here 148 | ... 149 | }; 150 | ``` 151 | 152 | ### Client Only 153 | 154 | This is when you already have a server running remotely and want your RPi to 155 | connect as a standalone client to this instance, to show the MM from the server. 156 | Then from your RPi, you run it with: 157 | `node clientonly --address 192.168.1.5 --port 8080`. (Specify the ip address and 158 | port number of the server) 159 | 160 | ### Wayland 161 | 162 | If you use Wayland. Run `npm run start:wayland` instead of `npm run start` to 163 | start. 164 | -------------------------------------------------------------------------------- /getting-started/requirements.md: -------------------------------------------------------------------------------- 1 | # Requirements 2 | 3 | ## Hardware 4 | 5 | MagicMirror² is developed to run on a Raspberry Pi. It might (and will) run on 6 | various different types of hardware, but new versions will only be tested on a 7 | Raspberry Pi. 8 | 9 | _Electron_, the app wrapper around MagicMirror², only supports the Raspberry Pi 10 | 2, 3, 4 & 5. The Raspberry Pi 0/1 is currently **not** supported. If you want to 11 | run this on a Raspberry Pi 1, use the [server only](installation.md#server-only) 12 | feature and setup a fullscreen browser yourself. (Yes, people have managed to 13 | run MM² also on a Pi0, so if you insist, search in the forums.) 14 | 15 | ## Operating System 16 | 17 | You will need to install the latest full version of 18 | [Raspberry Pi OS](https://www.raspberrypi.com/software/) (previously called 19 | Raspbian). 20 | 21 | If you want to run the software on other Operating Systems, take a look at 22 | [this section](/getting-started/installation.md#other-operating-systems) 23 | 24 | ::: warning NOTE You **do** need a desktop environment to run Electron! 25 | 26 | Using a Lite Version of Raspberry Pi OS **will not work**. 27 | 28 | Raspberry Pi OS versions based on Debian "Buster" are also no longer supported. 29 | ::: 30 | 31 | ## Node 32 | 33 | Please refer to the 34 | [release page](https://github.com/MagicMirrorOrg/MagicMirror/releases) to see 35 | which node version is required. 36 | -------------------------------------------------------------------------------- /getting-started/upgrade-guide.md: -------------------------------------------------------------------------------- 1 | # Upgrade Guide 2 | 3 | ::: danger WARNING 4 | 5 | Always backup your `config.js`, `custom.css` and `modules` folder before you 6 | start the upgrade process! 7 | 8 | ::: 9 | 10 | ## Manual Upgrade 11 | 12 | If you want to update your MagicMirror² to the latest version, use your terminal 13 | to go to your MagicMirror folder and type the following command: 14 | 15 | ```shell 16 | git pull && npm run install-mm 17 | ``` 18 | 19 | If you changed nothing more than the config or the modules, this should work 20 | without any problems. 21 | 22 | ::: danger WARNING 23 | 24 | Using `git reset --hard` as described below will delete all your changes made in 25 | the source code, so only execute this if you know what you are doing! 26 | 27 | ::: 28 | 29 | Type `git status` to see your changes, if there are any, you can reset them with 30 | `git reset --hard`. After that, `git pull` should be possible. 31 | 32 | MagicMirror² updates may change the minimum version of `Node.js` that is required, 33 | and the installation script above may fail if your system does not meet that 34 | minimum requirement. You can find information on installing newer versions of 35 | `Nodes.js` [here](https://github.com/nodesource/distributions) and 36 | [here](https://nodejs.org/en/download). And you can find information on the minimum 37 | version of `Node.js` that is required by MagicMirror² 38 | [here](https://github.com/MagicMirrorOrg/MagicMirror/releases) or by running the 39 | upgrade script above and reading any error messages. 40 | 41 | ## Alternative Upgrade Methods 42 | 43 | ::: tip NOTE 44 | 45 | Users who prefer a straightforward, automated solution may find alternative methods more practical. Although convenient, not using the manual method above may mean that you gain less insight into the system, which could make it harder to troubleshoot issues independently. 46 | 47 | ::: 48 | 49 | ### Community-Maintained Automatic Upgrade Script 50 | 51 | Sam (@sdetweil, long time contributor of the MagicMirror² framework) maintains an 52 | easy-to-use update script: 53 | [https://github.com/sdetweil/MagicMirror_scripts](https://github.com/sdetweil/MagicMirror_scripts/?tab=readme-ov-file#upgrade-to-next-magicmirror-version-from-an-existing-installation) 54 | -------------------------------------------------------------------------------- /modules/alert.md: -------------------------------------------------------------------------------- 1 | # Alert 2 | 3 | The alert module is one of the default modules of the MagicMirror. This module 4 | displays notifications from other modules. 5 | 6 | ## Usage 7 | 8 | To use this module, add it to the modules array in the config/config.js file: 9 | 10 | ``` 11 | modules: [ 12 | { 13 | module: "alert", 14 | config: { 15 | // The config property is optional. 16 | // See 'Configuration options' for more information. 17 | } 18 | } 19 | ] 20 | ``` 21 | 22 | ## Configuration options 23 | 24 | The following properties can be configured: 25 | 26 | | Option | Description | 27 | | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 28 | | `effect` | The animation effect to use for notifications.

**Possible values:** `scale` `slide` `genie` `jelly` `flip` `exploader` `bouncyflip`
**Default value:** `slide` | 29 | | `alert_effect` | The animation effect to use for alerts.

**Possible values:** `scale` `slide` `genie` `jelly` `flip` `exploader` `bouncyflip`
**Default value:** `jelly` | 30 | | `display_time` | Time a notification is displayed in milliseconds.

**Possible values:** `int`
**Default value:** `3500` | 31 | | `position` | Position where the notifications should be displayed.

**Possible values:** `left` `center` `right`
**Default value:** `center` | 32 | | `welcome_message` | Message shown at startup.

**Possible values:** `string` `false`
**Default value:** `false` (no message at startup) | 33 | 34 | ## Developer notes 35 | 36 | For notifications use: 37 | 38 | ``` 39 | self.sendNotification("SHOW_ALERT", {type: "notification"}); 40 | ``` 41 | 42 | For alerts use: 43 | 44 | ``` 45 | self.sendNotification("SHOW_ALERT", {}); 46 | ``` 47 | 48 | ### Notification params 49 | 50 | | Option | Description | 51 | | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- | 52 | | `title` | The title of the notification. Can contain text or html. | 53 | | `titleType` | The title type of the notification.

**Possible values:** `text` or `html`
**Default value:** `html` | 54 | | `message` | The message of the notification. Can contain text or html. | 55 | | `messageType` | The message type of the notification.

**Possible values:** `text` or `html`
**Default value:** `html` | 56 | | `timer` (optional) | How long the notification should stay visible in ms.
If absent, the default `display_time` is used.

**Possible values:** `int` `float` | 57 | 58 | ### Alert params 59 | 60 | | Option | Description | 61 | | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 62 | | `title` | The title of the alert. Can contain text or html. | 63 | | `titleType` | The title type of the alert.

**Possible values:** `text` or `html`
**Default value:** `html` | 64 | | `message` | The message of the alert. Can contain text or html. | 65 | | `messageType` | The message type of the alert.

**Possible values:** `text` or `html`
**Default value:** `html` | 66 | | `imageUrl` (optional) | Image to show in the alert

**Possible values:** `url` `path`
**Default value:** `none` | 67 | | `imageFA` (optional) | Font Awesome icon to show in the alert

**Possible values:** See [Font Awesome](https://fontawesome.com/v5.15/icons?m=free) website.
**Default value:** `none` | 68 | | `imageHeight` (optional even with imageUrl set) | Height of the image

**Possible values:** `intpx`
**Default value:** `80px` | 69 | | `timer` (optional) | How long the alert should stay visible in ms.

**Important:** If you do not use the `timer`, it is your duty to hide the alert by using `self.sendNotification("HIDE_ALERT");`!

**Possible values:** `int` `float`
**Default value:** `none` | 70 | 71 | ## Open Source Licenses 72 | 73 | ### [NotificationStyles](https://github.com/codrops/NotificationStyles) 74 | 75 | See [tympanus.net](https://tympanus.net/codrops/licensing/) for license. 76 | -------------------------------------------------------------------------------- /modules/animate.md: -------------------------------------------------------------------------------- 1 | # Animation Guide 2 | 3 | (_Introduced in version: 2.25.0_) 4 | 5 | ::: tip Preview of animation 6 | 7 | Check the [animate.css](https://animate.style/) library to see a preview of the 8 | animation name result. 9 | 10 | ::: 11 | 12 | ::: warning Where animation can be used? 13 | 14 | - [global module configuration](configuration.md#animated) of a module 15 | - [this.hide()](/development/core-module-file.md#this-hide-speed-callback-options) 16 | function in core module file 17 | - [this.show()](/development/core-module-file.md#this-show-speed-callback-options) 18 | function in core module file 19 | - [this.updateDom()](/development/core-module-file.md#this-updatedom-speed-options) 20 | function in core module file 21 | 22 | ::: 23 | 24 | ## animateIn 25 | 26 | When the module appears, you can choose an animation. 27 | 28 | Here is the list of names of special animations available: 29 | 30 | - bounce 31 | - flash 32 | - pulse 33 | - rubberBand 34 | - shakeX 35 | - shakeY 36 | - headShake 37 | - swing 38 | - tada 39 | - wobble 40 | - jello 41 | - heartBeat 42 | - backInDown 43 | - backInLeft 44 | - backInRight 45 | - backInUp 46 | - bounceIn 47 | - bounceInDown 48 | - bounceInLeft 49 | - bounceInRight 50 | - bounceInUp 51 | - fadeIn 52 | - fadeInDown 53 | - fadeInDownBig 54 | - fadeInLeft 55 | - fadeInLeftBig 56 | - fadeInRight 57 | - fadeInRightBig 58 | - fadeInUp 59 | - fadeInUpBig 60 | - fadeInTopLeft 61 | - fadeInTopRight 62 | - fadeInBottomLeft 63 | - fadeInBottomRight 64 | - flip 65 | - flipInX 66 | - flipInY 67 | - lightSpeedInRight 68 | - lightSpeedInLeft 69 | - rotateIn 70 | - rotateInDownLeft 71 | - rotateInDownRight 72 | - rotateInUpLeft 73 | - rotateInUpRight 74 | - jackInTheBox 75 | - rollIn 76 | - zoomIn 77 | - zoomInDown 78 | - zoomInLeft 79 | - zoomInRight 80 | - zoomInUp 81 | - slideInDown 82 | - slideInLeft 83 | - slideInRight 84 | - slideInUp 85 | 86 | ## animateOut 87 | 88 | When module should hide, you can choose an animation. 89 | 90 | Here is the list of names of special animations available: 91 | 92 | - backOutDown 93 | - backOutLeft 94 | - backOutRight 95 | - backOutUp 96 | - bounceOut 97 | - bounceOutDown 98 | - bounceOutLeft 99 | - bounceOutRight 100 | - bounceOutUp 101 | - fadeOut 102 | - fadeOutDown 103 | - fadeOutDownBig 104 | - fadeOutLeft 105 | - fadeOutLeftBig 106 | - fadeOutRight 107 | - fadeOutRightBig 108 | - fadeOutUp 109 | - fadeOutUpBig 110 | - fadeOutTopLeft 111 | - fadeOutTopRight 112 | - fadeOutBottomRight 113 | - fadeOutBottomLeft 114 | - flipOutX 115 | - flipOutY 116 | - lightSpeedOutRight 117 | - lightSpeedOutLeft 118 | - rotateOut 119 | - rotateOutDownLeft 120 | - rotateOutDownRight 121 | - rotateOutUpLeft 122 | - rotateOutUpRight 123 | - hinge 124 | - rollOut 125 | - zoomOut 126 | - zoomOutDown 127 | - zoomOutLeft 128 | - zoomOutRight 129 | - zoomOutUp 130 | - slideOutDown 131 | - slideOutLeft 132 | - slideOutRight 133 | - slideOutUp 134 | 135 | ::: warning WARN 136 | 137 | - You can't choose an `animateIn` name to place it on an `animateOut` and vice 138 | versa 139 | - Animation names are case sensitive 140 | - In case of wrong animation name, this will display the default animation 141 | (fade) 142 | 143 | ::: 144 | 145 | ## Developer Notes 146 | 147 | You can create an animation on a single `
` of your module. 148 | 149 | We coded `addAnimateCSS` and `removeAnimateCSS` in order to do this. 150 | 151 | ::: tip addAnimateCSS() function 152 | 153 | Allows you to add an animation to a single `
` of your module. 154 | 155 | ::: 156 | 157 | Syntax: `addAnimateCSS(
, , )` 158 | 159 | Sample: 160 | 161 | - You have created a `
` named "myDivSample" 162 | - You want to add a `flipInX` type animation for a duration of 1 second 163 | 164 | ```javascript 165 | addAnimateCSS("myDivSample", "flipInX", 1); 166 | ``` 167 | 168 | ::: tip removeAnimateCSS() function 169 | 170 | Allows you to remove an animation to a single `
` of your module 171 | 172 | ::: 173 | 174 | Syntax: `removeAnimateCSS(
, )` 175 | 176 | Sample: 177 | 178 | - You have created a `
` named "myDivSample" 179 | - You want to remove a `flipInX` type animation created with `addAnimateCSS()` 180 | function 181 | 182 | ```javascript 183 | removeAnimateCSS("myDivSample", "flipInX"); 184 | ``` 185 | 186 | ::: tip Tip 187 | 188 | You have to update only one element of your module. 189 | 190 | So, why not add an animation!? 191 | 192 | ::: 193 | 194 | ```javascript 195 | ... 196 | // select element ("myDivSample") 197 | let test = document.getElementById("myDivSample") 198 | // apply pretty update of this element 199 | test.textContent = "Hello AnimateCSS!" 200 | // add an "flipInX" animation type to "myDivSample" with 1 sec duration 201 | addAnimateCSS("myDivSample", "flipInX", 1) 202 | setTimeout(() => { 203 | // remove animation after 1sec 204 | removeAnimateCSS("myDivSample", "flipInX") 205 | }, 1000) 206 | ... 207 | ``` 208 | -------------------------------------------------------------------------------- /modules/clock.md: -------------------------------------------------------------------------------- 1 | # Clock 2 | 3 | The `clock` module is one of the default modules of the MagicMirror. This module 4 | displays the current date and time. The information will be updated realtime. 5 | 6 | ## Screenshot 7 | 8 | ![Clock screenshot](./screenshots/clock.png) 9 | 10 | ## Using the module 11 | 12 | To use this module, add it to the modules array in the `config/config.js` file: 13 | 14 | ```javascript 15 | modules: [ 16 | { 17 | module: "clock", 18 | position: "top_left", // This can be any of the regions. 19 | config: { 20 | // The config property is optional. 21 | // See 'Configuration options' for more information. 22 | }, 23 | }, 24 | ]; 25 | ``` 26 | 27 | ## Configuration options 28 | 29 | The following properties can be configured: 30 | 31 | | Option | Description | 32 | | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | 33 | | `timeFormat` | Use 12 or 24 hour format.

**Possible values:** `12` or `24`
**Default value:** uses value of _config.timeFormat_ | 34 | | `timezone` | Specific a timezone to show clock.

**Possible examples values:** `America/New_York`, `America/Santiago`, `Etc/GMT+10`
**Default value:** `none`. See more information about configuration value [here](https://momentjs.com/timezone/docs/#/data-formats/packed-format/) | 35 | | `displaySeconds` | Display seconds.

**Possible values:** `true` or `false`
**Default value:** `true` | 36 | | `showPeriod` | Show the period (am/pm) with 12 hour format.

**Possible values:** `true` or `false`
**Default value:** `true` | 37 | | `showPeriodUpper` | Show the period (AM/PM) with 12 hour format as uppercase.

**Possible values:** `true` or `false`
**Default value:** `false` | 38 | | `clockBold` | Remove the colon and bold the minutes to make a more modern look.

**Possible values:** `true` or `false`
**Default value:** `false` | 39 | | `showTime` | Turn off or on the Time section.

**Possible values:** `true` or `false`
**Default value:** `true` | 40 | | `showDate` | Turn off or on the Date section.

**Possible values:** `true` or `false`
**Default value:** `true` | 41 | | `showWeek` | Turn off or on the Week section.

**Possible values:** `true` or `false`
**Default value:** `false` | 42 | | `showSunTimes` | Turn off or on the section showing sunrise and sunset times (digital clock only).

**Possible values:** `true` or `false`
**Default value:** `false` | 43 | | `showMoonTimes` | Turn off or on the section showing moonrise and moonset times (digital clock only). Optionally display an image of lunar phase and lit percentage of the moon

**Possible values:** `times`, `percent`, `phase`, `both` or `false` (disable)
**Default value:** `false` | 44 | | `lat` | Latitude for sun/moon calculations.

**Default value:** `47.630539` | 45 | | `lon` | Longitude for sun/moon calculations.

**Default value:** `-122.344147` | 46 | | `dateFormat` | Configure the date format as you like.

**Possible values:** [Docs](https://momentjs.com/docs/#/displaying/format/)
**Default value:** `"dddd, LL"` | 47 | | `displayType` | Display a digital clock, analog clock, or both together.

**Possible values:** `digital`, `analog`, or `both`
**Default value:** `digital` | 48 | | `analogSize` | **Specific to the analog clock.** Defines how large the analog display is.

**Possible values:** `A positive number of pixels`
**Default value:** `200px` | 49 | | `analogFace` | **Specific to the analog clock.** Specifies which clock face to use.

**Possible values:** `simple` for a simple border, `none` for no face or border, or `face-###` (where ### is currently a value between 001 and 012, inclusive)
**Default value:** `simple` | 50 | | `secondsColor` | **Specific to the analog clock.** Specifies what color to make the 'seconds' hand.

**Possible values:** `any HTML RGB Color`
**Default value:** `#888888`
// starting in version 2.31.0 this property is DEPRECATED, and WILL be removed in some future version. Use CSS instead. Class "clock-second-digital" for digital clock, "clock-second" for analog clock. | 51 | | `analogPlacement` | **Specific to the analog clock. _(requires displayType set to `'both'`)_** Specifies where the analog clock is in relation to the digital clock

**Possible values:** `top`, `right`, `bottom`, or `left`
**Default value:** `bottom` | 52 | | `analogShowDate` | **Obsolete**, can be replaced with analogPlacement and showTime.

**Specific to the analog clock.** If the clock is used as a separate module and set to analog only, this configures whether a date is also displayed with the clock.

**Possible values:** `false`, `top`, or `bottom`
**Default value:** `top` | 53 | | `sendNotifications` | Enable notifications for elapsed time. Used to be always done send prio to v2.23

**Possible values:** `true`, or `false`
**Default value:** `false` | 54 | 55 | ## Notifications 56 | 57 | The clock makes use of the built-in 58 | [Notification Mechanism](https://github.com/magicmirrororg/magicmirror/wiki/notifications) 59 | to relay notifications to all modules. 60 | 61 | Current notifications are: 62 | 63 | | Notification | Description | 64 | | -------------- | ---------------------------------------------------- | 65 | | `CLOCK_SECOND` | A second has elapsed.
_Parameter_: second value | 66 | | `CLOCK_MINUTE` | A minute has elapsed
_Parameter_: minute value | 67 | 68 | ## styles for clock hands (analog) and text (digital) can be found in clock_style.css, use css/custom.css to override 69 | -------------------------------------------------------------------------------- /modules/compliments.md: -------------------------------------------------------------------------------- 1 | # Compliments 2 | 3 | The `compliments` module is one of the default modules of the MagicMirror. This 4 | module displays a random compliment. 5 | 6 | ## Screenshot 7 | 8 | ![Compliments Screenshot](./screenshots/compliments.png) 9 | 10 | ## Using the module 11 | 12 | To use this module, add it to the modules array in the `config/config.js` file: 13 | 14 | ```javascript 15 | modules: [ 16 | { 17 | module: "compliments", 18 | position: "lower_third", // This can be any of the regions. 19 | // Best results in one of the middle regions like: lower_third 20 | config: { 21 | // The config property is optional. 22 | // If no config is set, the default compliments are shown. 23 | // See 'Configuration options' for more information. 24 | }, 25 | }, 26 | ]; 27 | ``` 28 | 29 | ## Configuration options 30 | 31 | The following properties can be configured: 32 | 33 | | Option | Description | 34 | | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 35 | | `updateInterval` | How often does the compliment have to change? (Milliseconds)

**Possible values:** `1000` - `86400000`
**Default value:** `30000` (30 seconds) | 36 | | `fadeSpeed` | Speed of the update animation. (Milliseconds)

**Possible values:**`0` - `5000`
**Default value:** `4000` (4 seconds) | 37 | | `compliments` | The list of compliments.

**Possible values:** An object with four arrays: `morning`, `afternoon`, `evening` and `anytime`. See _compliment configuration_ below.
**Default value:** See _compliment configuration_ below. | 38 | | `remoteFile` | External file from which to load the compliments

**Possible values:** Path or URL (starting with `http://` or `https://`) to a JSON file containing compliments, configured as per the value of the _compliments configuration_ (see below). An json object {} with at least one of the arrays: `morning`, `afternoon`, `evening`, `anytime`, `datetype` and/or `crontype`. - `compliments.json`
**Default value:** `null` (Do not load from file) | 39 | | `remoteFileRefreshInterval` | How often to reload the remote file, if remoteFile is specified. in ms
**Default value:** 0
**Minimum value:** 15 minutes (15\*60\*60\*1000) | 40 | | `classes` | Override the CSS classes of the div showing the compliments

**Default value:** `thin xlarge bright` | 41 | | `morningStartTime` | Time in hours (in 24 format), after which the mode of "morning" will begin
**Possible values:** `0` - `24`

**Default value:** `3` | 42 | | `morningEndTime` | Time in hours (in 24 format), after which the mode of "morning" will end
**Possible values:** `0` - `24`

**Default value:** `12` | 43 | | `afternoonStartTime` | Time in hours (in 24 format), after which the mode "afternoon" will begin
**Possible values:** `0` - `24`

**Default value:** `12` | 44 | | `afternoonEndTime` | Time in hours (in 24 format), after which the mode "afternoon" will end
**Possible values:** `0` - `24`

**Default value:** `17` | 45 | | `specialDayUnique` | Compliments configured with a date are by default added to the existing compliments list. Setting this option to `true` will show only your special day compliments on that day. See _Example use with date_ below

**Default value:** `false` | 46 | 47 | All the rest of the time that does not fall into the 48 | morningStartTime-morningEndTime and afternoonStartTime-afternoonEndTime ranges 49 | is considered "evening". 50 | 51 | ### Compliment configuration 52 | 53 | The `compliments` property contains an object with at least four arrays: 54 | morning, afternoon, evening and 55 | anytime. Based on the time of the day, the compliments will be 56 | picked out of one of these arrays. The arrays contain one or multiple 57 | compliments. 58 | 59 | Compliments can be set for a specific day in the format `YYYY-MM-DD`. `.` can be 60 | used as a wildcard. 61 | 62 | starting in Version 2.29, the compliments configuration can use a cron type 63 | specification, which provides more options. In addition to date, one can use 64 | hours, minutes and day of week for additional control the cron format string is 65 | 5 groups of space separated values

**minute hour day month 66 | day_of_week**

each can be a range, and use numbers or names see 67 | https://crontab-generator.org for a visual cron syntax creator.. this tool asks 68 | for the command to be executed (cron is usually used to execute commands on a 69 | schedule), just use anything, and take the first 5 space separated tokens of the 70 | result. 71 | 72 | If set, the weather can be used for compliments. The available properties are: 73 | 74 | - `day_sunny` 75 | - `day_cloudy` 76 | - `cloudy` 77 | - `cloudy_windy` 78 | - `showers` 79 | - `rain` 80 | - `thunderstorm` 81 | - `snow` 82 | - `fog` 83 | - `night_clear` 84 | - `night_cloudy` 85 | - `night_showers` 86 | - `night_rain` 87 | - `night_thunderstorm` 88 | - `night_snow` 89 | - `night_alt_cloudy_windy` 90 | 91 | #### Example use with date 92 | 93 | ```javascript 94 | config: { 95 | compliments: { 96 | "....-01-01": [ 97 | "Happy new year!" 98 | ], 99 | "....-10-31": [ 100 | "Happy Halloween!" 101 | ] 102 | } 103 | } 104 | ``` 105 | 106 | #### Example use with a cron entry 107 | 108 | ```javascript 109 | config: { 110 | compliments: { 111 | "48-50 16-18 * * 5,6": [ 112 | "Happy Hour!", "Its a Party" 113 | ] 114 | } 115 | } 116 | ``` 117 | 118 | this means, on Friday or Saturday, every week (\* (every) month/day) between 119 | 16:48-16:50, 17:48-17:50, and 18:48-18:50, the assigned messages will be used. 120 | note: like with the date only setting, if these are the only possible messages 121 | you want displayed, you need to set **specialDayUnique:true** 122 | 123 | As another example you could use this for scary messages ONLY between 8 and 9pm 124 | on Halloween evening: 125 | 126 | ```javascript 127 | config: { 128 | compliments: { 129 | "* 20-21 31 10 *": [ 130 | "Boo!!" 131 | ] 132 | } 133 | } 134 | ``` 135 | 136 | #### Example use with weather module 137 | 138 | ```javascript 139 | config: { 140 | compliments: { 141 | day_sunny: [ 142 | "Today is a sunny day", 143 | "It's a beautiful day" 144 | ], 145 | snow: [ 146 | "Snowball battle!" 147 | ], 148 | rain: [ 149 | "Don't forget your umbrella" 150 | ] 151 | } 152 | } 153 | ``` 154 | 155 | #### Default value: 156 | 157 | ```javascript 158 | config: { 159 | compliments: { 160 | anytime: [ 161 | "Hey there sexy!" 162 | ], 163 | morning: [ 164 | "Good morning, handsome!", 165 | "Enjoy your day!", 166 | "How was your sleep?" 167 | ], 168 | afternoon: [ 169 | "Hello, beauty!", 170 | "You look sexy!", 171 | "Looking good today!" 172 | ], 173 | evening: [ 174 | "Wow, you look hot!", 175 | "You look nice!", 176 | "Hi, sexy!" 177 | ], 178 | "....-01-01": [ 179 | "Happy new year!" 180 | ] 181 | } 182 | } 183 | ``` 184 | 185 | #### Multi-line compliments: 186 | 187 | Use `\n` to split compliment text into multiple lines, e.g. 188 | `First line.\nSecond line.` will be shown as: 189 | 190 | ``` 191 | First line. 192 | Second line. 193 | ``` 194 | 195 | ### External Compliment File 196 | 197 | You may specify an external file that contains the three compliment arrays. This 198 | is particularly useful if you have a large number of compliments and do not wish 199 | to crowd your `config.js` file with a large array of compliments. Adding the 200 | `remoteFile` variable will override an array you specify in the configuration 201 | file. 202 | 203 | This file must be straight JSON. Note that the array names need quotes around 204 | them ("morning", "afternoon", "evening", "snow", "rain", etc.). 205 | 206 | #### Example config/config.js of a Compliment File hosted on GitHub 207 | 208 | ``` 209 | { 210 | module: 'compliments', 211 | position: 'middle_center', 212 | config: { 213 | remoteFile: 'https://gist.githubusercontent.com/user/e28a69665b8839f6e9a7acd6b4acc97d/raw/be1dee8f805a433f6ee0fa3556d1927da14e7799/compliments.json' 214 | } 215 | }, 216 | 217 | ``` 218 | 219 | (When copying the link from Github, you must use the 'Raw' link) 220 | 221 | #### Example compliments.json file: 222 | 223 | ```json 224 | { 225 | "anytime": ["Hey there sexy!"], 226 | "morning": [ 227 | "Good morning, sunshine!", 228 | "Who needs coffee when you have your smile?", 229 | "Go get 'em, Tiger!" 230 | ], 231 | "afternoon": [ 232 | "Hitting your stride!", 233 | "You are making a difference!", 234 | "You're more fun than bubble wrap!" 235 | ], 236 | "evening": [ 237 | "You made someone smile today, I know it.", 238 | "You are making a difference.", 239 | "The day was better for your efforts." 240 | ] 241 | } 242 | ``` 243 | -------------------------------------------------------------------------------- /modules/configuration.md: -------------------------------------------------------------------------------- 1 | # Module Configuration 2 | 3 | The module configuration is used as part of the main configuration file. Please 4 | see [configuration](/configuration/introduction.md) for more information. 5 | 6 | | **Option** | **Description** | 7 | | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | 8 | | `module` | The name of the module. This can also contain the subfolder. Valid examples include `clock`, `default/calendar` and `custommodules/mymodule`. | 9 | | `position` | The location of the module in which the module will be loaded. The built in values are `top_bar`, `top_left`, `top_center`, `top_right`, `upper_third`, `middle_center`, `lower_third`, `bottom_left`, `bottom_center`, `bottom_right`, `bottom_bar`, `fullscreen_above`, and `fullscreen_below`. This field is optional but most modules require this field to set. (if not set, the module will not be shown, but will run the same) Check the documentation of the module for more information. Multiple modules with the same position will be ordered based on the order in the configuration file, top down. | 10 | | | Note:

if your implementation of MagicMirror wishes to use custom position values, they need to be used in **index.html** , and in the format

class="region newpos-a newpos-b"

MagicMirror will join the last two terms with an underscore to make a position value like

newpos-a_newpos-b

example: class="region top3 left"
the position will be "top3_left"

newpos_b is optional
class="region top3" would be valid and produce a position of "top3"

the new position values will be checked during MagicMirror startup and also in the configuration checker
npm run config:check

AND you have to have the appropriate css settings in custom.css for these new region values (top3 and left as used in the example above) | 11 | | `classes` | One or more additional CSS classes which will be set on the module, as a string of space-separated values. This field is optional. | 12 | | `header` | To display a header text above the module, add the header property. This field is optional. | 13 | | `hiddenOnStartup` | Set module as being hidden on startup. This field is optional. | 14 | | `disabled` | Set disabled to `true` to skip creating the module. This field is optional. | 15 | | `configDeepMerge` | Allow to merge with internal configuration in deep (Array and/with object). This field is optional (on developer choice generaly). | 16 | | `animateIn` | Special animate name when a module appears (see below) This field is optional. | 17 | | `animateOut` | Special animates name when a module should hide (see below) This field is optional. | 18 | | `config` | An object with the module configuration properties. Check the documentation of the module for more information. This field is optional, unless the module requires extra configuration. | 19 | 20 | ## Example 21 | 22 | ```javascript 23 | let config = { 24 | modules: [ 25 | { 26 | module: "clock", 27 | position: "top_left", 28 | }, 29 | { 30 | module: "compliments", 31 | position: "lower_third", 32 | }, 33 | { 34 | module: "weather", 35 | position: "top_right", 36 | classes: "myclass1 myclass2", 37 | config: { 38 | weatherProvider: "openweathermap", 39 | type: "current", 40 | location: "New York", 41 | locationID: "5128581", //ID from http://bulk.openweathermap.org/sample/city.list.json.gz; unzip the gz file and find your city 42 | apiKey: "YOUR_OPENWEATHER_API_KEY", 43 | }, 44 | }, 45 | ], 46 | }; 47 | ``` 48 | 49 | ## Position 50 | 51 | The locations can be found in the following screenshot by their color: 52 | 53 | - `top_bar` and `bottom_bar` are light gray 54 | - `top_left` and `bottom_left` are red 55 | - `top_center` and `bottom_center` are blue 56 | - `top_right` and `bottom_right` are green 57 | - `upper_third` is yellow 58 | - `middle_center` is cyan 59 | - `lower_third` is magenta 60 | 61 | ![Screenshot of Regions](./screenshots/regions.png) 62 | 63 | Missing are the fullscreen_below and fullscreen_above as those cover the whole 64 | screen, one under everything else and the other above. 65 | 66 | All these regions will resize as needed. 67 | 68 | ## Animated 69 | 70 | (_Introduced in version: 2.25.0_) 71 | 72 | Animated feature allows to define an animation to a module 73 | 74 | - `animateIn`: When module appears 75 | - `animateOut`: When module should hide 76 | 77 | The whole of animation names are available [there](animate.md). 78 | 79 | ::: tip Preview of animations 80 | 81 | Check the [animate.css](https://animate.style/) library to see a preview of the 82 | animation name result 83 | 84 | ::: 85 | 86 | ### Example with `newsfeed` module 87 | 88 | For this example, news will come from the left (`slideInLeft` animation), wait 89 | in the middle, and exit from the right (`slideOutRight` animation) 90 | 91 | ![animateCSS](./screenshots/animate.gif) 92 | 93 | ```javascript 94 | { 95 | module: "newsfeed", 96 | position: "bottom_bar", 97 | animateIn: "slideInLeft", 98 | animateOut: "slideOutRight", 99 | config: { 100 | feeds: [ 101 | { 102 | title: "New York Times", 103 | url: "https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml" 104 | } 105 | ], 106 | showSourceTitle: true, 107 | showPublishDate: true, 108 | broadcastNewsFeeds: true, 109 | broadcastNewsUpdates: true 110 | } 111 | }, 112 | ``` 113 | -------------------------------------------------------------------------------- /modules/customcss.md: -------------------------------------------------------------------------------- 1 | # Custom CSS 2 | 3 | MagicMirror² comes with a default theme but it can be customized by placing a 4 | custom css-file in `css/custom.css`. 5 | 6 | ### Example 7 | 8 | One common request is to make the weather icons colorful, this can easily be 9 | achieved in the custom css, this makes the sunny weather icon yellow: 10 | 11 | ```css 12 | .wi-day-sunny { 13 | color: #ffff00; 14 | } 15 | ``` 16 | 17 | MagicMirror² uses these weather icons: 18 | [https://erikflowers.github.io/weather-icons/](http://erikflowers.github.io/weather-icons/). 19 | On that page you can find what class name is used for the displayed icon and add 20 | it to your `custom.css`-file like in the example above. 21 | 22 | ### Target a specific module 23 | 24 | Each module has a class set for the div it resides in named after the module 25 | (including all the 3rd-party modules). As an example the 26 | [Clock-module](https://github.com/MagicMirrorOrg/MagicMirror/tree/master/modules/default/clock) 27 | could be customized by using the class `.clock`. 28 | 29 | ### Help 30 | 31 | For questions and inspiration visit the 32 | [forum category](https://forum.magicmirror.builders/category/8/custom-css) 33 | dedicated to this. 34 | -------------------------------------------------------------------------------- /modules/helloworld.md: -------------------------------------------------------------------------------- 1 | # Hello World 2 | 3 | The `helloworld` module is one of the default modules of the MagicMirror. It is 4 | a simple way to display a static text on the mirror. 5 | 6 | ## Using the module 7 | 8 | To use this module, add it to the modules array in the `config/config.js` file: 9 | 10 | ```javascript 11 | modules: [ 12 | { 13 | module: "helloworld", 14 | position: "bottom_bar", // This can be any of the regions. 15 | config: { 16 | // See 'Configuration options' for more information. 17 | text: "Hello world!", 18 | }, 19 | }, 20 | ]; 21 | ``` 22 | 23 | ## Configuration options 24 | 25 | The following properties can be configured: 26 | 27 | | Option | Description | 28 | | ------ | ---------------------------------------------------------------------------------------------------- | 29 | | `text` | The text to display.

**Example:** `'Hello world!'`
**Default value:** `'Hello world!'` | 30 | -------------------------------------------------------------------------------- /modules/introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Introduction 3 | --- 4 | 5 | # Modules 6 | 7 | The following modules are installed by default. 8 | 9 | - [**Clock**](clock.md) 10 | - [**Calendar**](calendar.md) 11 | - [**Weather**](weather.md) 12 | - [**News Feed**](newsfeed.md) 13 | - [**Compliments**](compliments.md) 14 | - [**Hello World**](helloworld.md) 15 | - [**Alert**](alert.md) 16 | 17 | For more available modules, check out out the wiki page 18 | [MagicMirror² 3rd Party Modules](https://github.com/MagicMirrorOrg/MagicMirror/wiki/3rd-party-modules). 19 | If you want to build your own modules, check out the 20 | [MagicMirror² Module Development Documentation](/development/introduction.md) 21 | and don't forget to add it to the 22 | [wiki](https://github.com/MagicMirrorOrg/MagicMirror/wiki) and the 23 | [forum](https://forum.magicmirror.builders/category/7/showcase)! 24 | -------------------------------------------------------------------------------- /modules/newsfeed.md: -------------------------------------------------------------------------------- 1 | # News Feed 2 | 3 | The `newsfeed ` module is one of the default modules of the MagicMirror. This 4 | module displays news headlines based on an RSS feed. Scrolling through news 5 | headlines happens time-based (`updateInterval`), but can also be controlled by 6 | sending news feed specific notifications to the module. 7 | 8 | ## Screenshot 9 | 10 | ![NYT News Feed Screenshot](./screenshots/newsfeed.png) 11 | 12 | ## Using the module 13 | 14 | ### Configuration 15 | 16 | To use this module, add it to the modules array in the `config/config.js` file: 17 | 18 | ```javascript 19 | modules: [ 20 | { 21 | module: "newsfeed", 22 | position: "bottom_bar", // This can be any of the regions. Best results in center regions. 23 | config: { 24 | // The config property is optional. 25 | // If no config is set, an example calendar is shown. 26 | // See 'Configuration options' for more information. 27 | 28 | feeds: [ 29 | { 30 | title: "New York Times", 31 | url: "https://www.nytimes.com/services/xml/rss/nyt/HomePage.xml", 32 | }, 33 | { 34 | title: "BBC", 35 | url: "https://feeds.bbci.co.uk/news/video_and_audio/news_front_page/rss.xml?edition=uk", 36 | }, 37 | ], 38 | }, 39 | }, 40 | ]; 41 | ``` 42 | 43 | ### Notifications 44 | 45 | #### Interacting with the module 46 | 47 | MagicMirror's 48 | [notification mechanism](https://github.com/MagicMirrorOrg/MagicMirror/tree/master/modules#thissendnotificationnotification-payload) 49 | allows to send notifications to the `newsfeed` module. The following 50 | notifications are supported: 51 | 52 | | Notification Identifier | Description | 53 | | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 54 | | `ARTICLE_NEXT` | Shows the next news title (hiding the summary or previously fully displayed article) | 55 | | `ARTICLE_PREVIOUS` | Shows the previous news title (hiding the summary or previously fully displayed article) | 56 | | `ARTICLE_MORE_DETAILS` | When received the _first time_, shows the corresponding description of the currently displayed news title.
The module expects that the module's configuration option `showDescription` is set to `false` (default value).

When received a _second consecutive time_, shows the full news article in an IFRAME.
This requires that the news page can be embedded in an IFRAME, e.g. doesn't have the HTTP response header [X-Frame-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options) set to e.g. `DENY`.

When received the _next consecutive times_, reloads the page and scrolls down by `scrollLength` pixels to paginate through the article. | 57 | | `ARTICLE_LESS_DETAILS` | Hides the summary or full news article and only displays the news title of the currently viewed news item. | 58 | | `ARTICLE_TOGGLE_FULL` | Toggles article in fullscreen. | 59 | | `ARTICLE_INFO_REQUEST` | Causes `newsfeed` to respond with the notification `ARTICLE_INFO_RESPONSE`, the payload of which provides the `title`, `source`, `date`, `desc` and `url` of the current news title. | 60 | 61 | #### Notifications sent by the module 62 | 63 | MagicMirror's 64 | [notification mechanism](https://github.com/MagicMirrorOrg/MagicMirror/tree/master/modules#thissendnotificationnotification-payload) 65 | can also be used to send notifications from the current module to all other 66 | modules. The following notifications are broadcasted from this module: 67 | 68 | | Notification Identifier | Description | 69 | | ----------------------- | ------------------------------------------ | 70 | | `NEWS_FEED` | Broadcast the current list of news items. | 71 | | `NEWS_FEED_UPDATE` | Broadcasts the list of updates news items. | 72 | 73 | Note the payload of the sent notification event is ignored. 74 | 75 | #### Example 76 | 77 | The following example shows how the next news article title can be displayed on 78 | the MagicMirror. 79 | 80 | ```javascript 81 | this.sendNotification("ARTICLE_NEXT"); 82 | ``` 83 | 84 | #### `newsfeed` specific notification emitting modules 85 | 86 | The third party [MMM-Gestures](https://github.com/thobach/MMM-Gestures) module 87 | supports above notifications when moving your hand up, down, left or right in 88 | front of a gesture sensor attached to the MagicMirror. See module's readme for 89 | more details. 90 | 91 | ## Configuration options 92 | 93 | The following properties can be configured: 94 | 95 | | Option | Description | 96 | | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 97 | | `feeds` | An array of feed urls that will be used as source.
More info about this object can be found below.
**Default value:** `[{ title: "New York Times", url: "https://www.nytimes.com/services/xml/rss/nyt/HomePage.xml", encoding: "UTF-8" }]`
You can add `reloadInterval` option to set particular reloadInterval to a feed. | 98 | | `showAsList` | Display the news as a list.

**Possible values:** `true` or `false`
**Default value:** `false` | 99 | | `showSourceTitle` | Display the title of the source.

**Possible values:** `true` or `false`
**Default value:** `true` | 100 | | `showPublishDate` | Display the publish date of an headline.

**Possible values:** `true` or `false`
**Default value:** `true` | 101 | | `broadcastNewsFeeds` | Gives the ability to broadcast news feeds to all modules, by using `sendNotification()` when set to `true`, rather than `sendSocketNotification()` when `false`

**Possible values:** `true` or `false`
**Default value:** `true` | 102 | | `broadcastNewsUpdates` | Gives the ability to broadcast news feed updates to all modules

**Possible values:** `true` or `false`
**Default value:** `true` | 103 | | `showDescription` | Display the description of an item.

**Possible values:** `true` or `false`
**Default value:** `false` | 104 | | `showTitleAsUrl` | If set, the displayed title is a link to the article which is useful when running in a browser and you want to read this article.

**Possible values:** `true` or `false`
**Default value:** `false` | 105 | | `wrapTitle` | Wrap the title of the item to multiple lines.

**Possible values:** `true` or `false`
**Default value:** `true` | 106 | | `wrapDescription` | Wrap the description of the item to multiple lines.

**Possible values:** `true` or `false`
**Default value:** `true` | 107 | | `truncDescription` | Truncate description?

**Possible values:** `true` or `false`
**Default value:** `true` | 108 | | `lengthDescription` | How many characters to be displayed for a truncated description?

**Possible values:** `1` - `500`
**Default value:** `400` | 109 | | `hideLoading` | Hide module instead of showing LOADING status.

**Possible values:** `true` or `false`
**Default value:** `false` | 110 | | `reloadInterval` | How often does the content needs to be fetched? (Milliseconds)

**Possible values:** `1000` - `86400000`
**Default value:** `300000` (5 minutes) | 111 | | `updateInterval` | How often do you want to display a new headline? (Milliseconds)

**Possible values:**`1000` - `60000`
**Default value:** `10000` (10 seconds) | 112 | | `animationSpeed` | Speed of the update animation. (Milliseconds)

**Possible values:**`0` - `5000`
**Default value:** `2500` (2.5 seconds) | 113 | | `maxNewsItems` | Total amount of news items to cycle through. (0 for unlimited)

**Possible values:**`0` - `...`
**Default value:** `0` | 114 | | `ignoreOldItems` | Ignore news items that are outdated.

**Possible values:**`true` or `false`
**Default value:** `false` | 115 | | `ignoreOlderThan` | How old should news items be before they are considered outdated? (Milliseconds)

**Possible values:**`1` - `...`
**Default value:** `86400000` (1 day) | 116 | | `removeStartTags` | Some news feeds feature tags at the **beginning** of their titles or descriptions, such as _[VIDEO]_. This setting allows for the removal of specified tags from the beginning of an item's description and/or title.

**Possible values:**`'title'`, `'description'`, `'both'` | 117 | | `startTags` | List the tags you would like to have removed at the beginning of the feed item

**Possible values:** `['TAG']` or `['TAG1','TAG2',...]` | 118 | | `removeEndTags` | Remove specified tags from the **end** of an item's description and/or title.

**Possible values:**`'title'`, `'description'`, `'both'` | 119 | | `endTags` | List the tags you would like to have removed at the end of the feed item

**Possible values:** `['TAG']` or `['TAG1','TAG2',...]` | 120 | | `prohibitedWords` | Remove news feed item if one of these words is found anywhere in the title (case insensitive and greedy matching)

**Possible values:** `['word']` or `['word1','word2',...]` | 121 | | `scrollLength` | Scrolls the full news article page by a given number of pixels when a `ARTICLE_MORE_DETAILS` notification is received and the full news article is already displayed.

**Possible values:** `1` or `10000`
**Default value:** `500` | 122 | | `logFeedWarnings` | Log warnings when there is an error parsing a news article.

**Possible values:** `true` or `false`
**Default value:** `false` | 123 | 124 | The `feeds` property contains an array with multiple objects. These objects have 125 | the following properties: 126 | 127 | | Option | Description | 128 | | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | 129 | | `title` | The name of the feed source to be displayed above the news items.

This property is optional. | 130 | | `url` | The url of the feed used for the headlines.

**Example:** `'https://www.nytimes.com/services/xml/rss/nyt/HomePage.xml'` | 131 | | `encoding` | The encoding of the news feed.

This property is optional.
**Possible values:** `'UTF-8'`, `'ISO-8859-1'`, etc ...
**Default value:** `'UTF-8'` | 132 | | `useCorsProxy` | Uses the internal cors proxy to avoid cors errors.

This property is optional.
**Possible values:** `true` or `false`
**Default value:** `true` | 133 | | `ignoreOldItems` | Overrides the property defined for the module (see above) for the specific feed | 134 | | `ignoreOlderThan` | Overrides the property defined for the module (see above) for the specific feed | 135 | -------------------------------------------------------------------------------- /modules/screenshots/animate.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MagicMirrorOrg/MagicMirror-Documentation/691533aaaa1e272d194f5f60216e0751ba0bddb0/modules/screenshots/animate.gif -------------------------------------------------------------------------------- /modules/screenshots/clock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MagicMirrorOrg/MagicMirror-Documentation/691533aaaa1e272d194f5f60216e0751ba0bddb0/modules/screenshots/clock.png -------------------------------------------------------------------------------- /modules/screenshots/compliments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MagicMirrorOrg/MagicMirror-Documentation/691533aaaa1e272d194f5f60216e0751ba0bddb0/modules/screenshots/compliments.png -------------------------------------------------------------------------------- /modules/screenshots/customEvents_transform_after.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MagicMirrorOrg/MagicMirror-Documentation/691533aaaa1e272d194f5f60216e0751ba0bddb0/modules/screenshots/customEvents_transform_after.png -------------------------------------------------------------------------------- /modules/screenshots/customEvents_transform_before.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MagicMirrorOrg/MagicMirror-Documentation/691533aaaa1e272d194f5f60216e0751ba0bddb0/modules/screenshots/customEvents_transform_before.png -------------------------------------------------------------------------------- /modules/screenshots/newsfeed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MagicMirrorOrg/MagicMirror-Documentation/691533aaaa1e272d194f5f60216e0751ba0bddb0/modules/screenshots/newsfeed.png -------------------------------------------------------------------------------- /modules/screenshots/regions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MagicMirrorOrg/MagicMirror-Documentation/691533aaaa1e272d194f5f60216e0751ba0bddb0/modules/screenshots/regions.png -------------------------------------------------------------------------------- /modules/screenshots/weather_current.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MagicMirrorOrg/MagicMirror-Documentation/691533aaaa1e272d194f5f60216e0751ba0bddb0/modules/screenshots/weather_current.png -------------------------------------------------------------------------------- /modules/screenshots/weather_forecast.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MagicMirrorOrg/MagicMirror-Documentation/691533aaaa1e272d194f5f60216e0751ba0bddb0/modules/screenshots/weather_forecast.png -------------------------------------------------------------------------------- /modules/updatenotification.md: -------------------------------------------------------------------------------- 1 | # Update Notification 2 | 3 | The `updatenotification` module is one of the default modules of the 4 | MagicMirror. This will display a message whenever a new version of the 5 | MagicMirror application is available. 6 | 7 | ## Using the module 8 | 9 | To use this module, add it to the modules array in the `config/config.js` file: 10 | 11 | ```javascript 12 | modules: [ 13 | { 14 | module: "updatenotification", 15 | position: "top_center", // This can be any of the regions. 16 | config: { 17 | // The config property is optional. 18 | // See 'Configuration options' for more information. 19 | }, 20 | }, 21 | ]; 22 | ``` 23 | 24 | ## Configuration options 25 | 26 | The following properties can be configured: 27 | 28 | | Option | Description | 29 | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 30 | | `updateInterval` | How often do you want to check for a new version? This value represents the interval in milliseconds.

**Possible values:** Any value above `60000` (1 minute)
**Default value:** `600000` (10 minutes) | 31 | | `ignoreModules` | An array of module names that should not check for update.

**Example:** `["MMM-ExampleModule1", "MMM-ExampleModule2"]`.
You can exclude MagicMirror by adding "MagicMirror" to the array.
**Default value:** `[]` (empty array, no modules) | 32 | | `sendUpdatesNotifications` | Allow to broadcast update with **UPDATES** notification to other modules.

**Default value:** `false` | 33 | | `updates` | Array of updates modules commands.
**Default value:** `[]` (see bellow) | 34 | | `updateTimeout` | Maximum Update duration before cancel it.
**Default Value:** `120000` (2 minutes) | 35 | | `updateAutorestart` | Restart automaticaly MagicMirror² after update is done.
**Default Value:** `false` | 36 | | `useModulesFromConfig` | If `false` iterate over modules directory instead using modules defined in `config.js`.
**Default Value:** `true` | 37 | 38 | ### `updates` Array 39 | 40 | `updates` is an array of command for updating 3rd party modules modules 41 | 42 | It consists of an object containing the name of the module and the associated 43 | update command 44 | 45 | Sample: 46 | 47 | ```javascript 48 | modules: [ 49 | { 50 | module: "updatenotification", 51 | position: "top_center", // This can be any of the regions. 52 | config: { 53 | updates: [ 54 | // array of module update commands 55 | { 56 | // update of MMM-Test with embed npm script 57 | "MMM-Test": "npm run update", 58 | }, 59 | { 60 | // update of MMM-OtherSample with "complex" process command 61 | "MMM-OtherSample": 62 | "rm -rf package-lock.json && git reset --hard && git pull && npm install", 63 | }, 64 | { 65 | // update of MMM-OtherSample2 with git pull && npm install command 66 | "MMM-OtherSample2": "git pull && npm install", 67 | }, 68 | { 69 | // update of MMM-OtherSample3 with a simple git pull 70 | "MMM-OtherSample3": "git pull", 71 | }, 72 | ], 73 | }, 74 | }, 75 | ]; 76 | ``` 77 | 78 | Note: Don’t hesitate to ask the module developer for the ideal command to update 79 | their module. 80 | 81 | ## Developer notes 82 | 83 | ### Broadcast notifications (notifications send to modules) 84 | 85 | | Notification | Description | Requirement | 86 | | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | 87 | | UPDATES | When updates are available, an Array of updatable modules is sended.
This is the best way to update your own module! (a guide will be available soon)
Note: It will not include default modules and MagicMirror.

**Example:** `["MMM-MyOwnModule","MMM-Test"]` | `sendUpdatesNotifications: true` | 88 | 89 | ### Received notification (notifications send from modules) 90 | 91 | | Notification | Description | 92 | | ------------ | --------------------------------------------------- | 93 | | SCAN_UPDATES | Allow force scanning any updates from other modules | 94 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.31.0", 3 | "devDependencies": { 4 | "@vuepress/bundler-vite": "^2.0.0-rc.21", 5 | "@vuepress/plugin-back-to-top": "^2.0.0-rc.94", 6 | "@vuepress/plugin-docsearch": "^2.0.0-rc.95", 7 | "@vuepress/plugin-google-analytics": "^2.0.0-rc.94", 8 | "@vuepress/theme-default": "^2.0.0-rc.95", 9 | "cspell": "^8.18.1", 10 | "prettier": "^3.5.3", 11 | "prettier-config-vuepress": "^5.0.0", 12 | "sass-embedded": "^1.86.3", 13 | "vue": "^3.5.13", 14 | "vuepress": "^2.0.0-rc.21" 15 | }, 16 | "scripts": { 17 | "start": "npm run docs:dev", 18 | "docs:dev": "vuepress dev .", 19 | "docs:build": "vuepress build .", 20 | "lint": "prettier . --write", 21 | "test": "npm run test:format && npm run test:spelling", 22 | "test:format": "prettier . --check", 23 | "test:spelling": "cspell . --gitignore" 24 | } 25 | } 26 | --------------------------------------------------------------------------------