Add initial support for custom stylesheets (#7164)

* Add initial support for custom stylesheets Allow an override file `custom.css` that can partially override the stylesheet used for the web interface. # Changes 1. Update default views to use custom stylesheet 2. Update documentation Related to: https://github.com/Ylianst/MeshCentral/issues/7144 * Add custom style support to more views Load `custom.css` in the following views: - agentinvite.handlebars - invite.handlebars - login2.handlebars - message2.handlebars - messenger.handlebars - player.handlebars - sharing.handlebars

bundabrg committed Jul 19, 2025 at 04:06 UTC a7633d27c567ce68e8d9516948b319e9073560ef
12 files changed +39
docs/docs/meshcentral/customization.md
+30
@@ -59,6 +59,36 @@ To update device icons, you need to edit these files: `meshcentral-web/public/im
59 By following these steps, you can customize any icon in MeshCentral. Just find and change the corresponding image files in the `meshcentral-web/public/images` folder. Similarly, you can also move other folders from `node_modules/meshcentral` to `meshcentral-web` while keeping the original folder structure. This allows you to modify other parts of MeshCentral too, like the `.handlebars` templates for the web interface. Simply copy files from `node_modules/meshcentral/views` to `meshcentral-web/views` and make your changes in `meshcentral-web`. This lets you match MeshCentral's look to your company's brand or your own style.
60 ![](images/custom-web-icons.png)
61
62 +### Customizing Web Style
63 +MeshCentral gives you the flexibility to override some or all of the web interface. An easy way to modify the style is to do the following:
64 +
65 +1. Create the file `custom.css` under `meshcentral-web/public/styles`. See [above](#customizing-web-style) for more information on `meshcentral-web`.
66 +2. Anything added to this file will override the default stylesheets.
67 +
68 +An example file:
69 +
70 +```css
71 +#masthead {
72 + background-color: red;
73 +}
74 +
75 +#page_leftbar {
76 + background: linear-gradient(to bottom, #104893 0%,green 100%)
77 +}
78 +
79 +#footer {
80 + background-color: green;
81 +}
82 +```
83 +
84 +Gives:
85 +
86 +![Custom Style](images/custom-style-example.png)
87 +
88 +!!!note
89 +You can of course override the stylesheets by directly copying them into `meshcentral-web/public/styles` but run the risk that future updates to those files in MeshCentral will be masked. `custom.css` is guaranteed to be loaded last on every page and will contain no content by default which means upgrades will work as normal.
90 +
91 +
92 ### Customizing Agent Invitation
93 Agents can be invited by public link or via email. [Click Here](assistant.md#agent-invitation) to see details.
94
docs/docs/meshcentral/images/custom-style-example.png
Binary files /dev/null and b/docs/docs/meshcentral/images/custom-style-example.png differ
public/styles/custom.css
views/agentinvite.handlebars
+1
@@ -8,6 +8,7 @@
8 <meta name="format-detection" content="telephone=no" />
9 <meta name="robots" content="noindex,nofollow" />
10 <link type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS" />
11 + <link type="text/css" href="styles/custom.css" media="screen" rel="stylesheet" title="CSS" />
12 <link rel="apple-touch-icon" href="/favicon-303x303.png" />
13 <script type="text/javascript" src="scripts/common-0.0.1{{min}}.js"></script>
14 <script type="text/javascript" src="scripts/qrcode.min.js"></script>
views/default.handlebars
+1
@@ -14,6 +14,7 @@
14 <link type="text/css" href="styles/ol3-contextmenu.min.css" media="screen" rel="stylesheet" title="CSS" />
15 <link type="text/css" href="styles/xterm.css" media="screen" rel="stylesheet" title="CSS" />
16 <link type="text/css" href="styles/flatpickr.min.css" media="screen" rel="stylesheet" title="CSS">
17 + <link type="text/css" href="styles/custom.css" media="screen" rel="stylesheet" title="CSS" />
18 <link rel="apple-touch-icon" href="/favicon-303x303.png" />
19 <script type="text/javascript" src="scripts/common-0.0.1{{{min}}}.js"></script>
20 <script type="text/javascript" src="scripts/meshcentral{{{min}}}.js"></script>
views/default3.handlebars
+1
@@ -18,6 +18,7 @@
18 <link id="theme-stylesheet" href="styles/bootstrap{{{min}}}.css" rel="stylesheet" title="CSS">
19 <link href="styles/select2.min.css" rel="stylesheet" title="CSS">
20 <link href="styles/select2-bootstrap-5-theme.min.css" rel="stylesheet" title="CSS">
21 + <link type="text/css" href="styles/custom.css" media="screen" rel="stylesheet" title="CSS" />
22 <link rel="apple-touch-icon" href="/favicon-303x303.png" />
23 <script type="text/javascript" src="scripts/common-0.0.1{{{min}}}.js"></script>
24 <script type="text/javascript" src="scripts/meshcentral{{{min}}}.js"></script>
views/invite.handlebars
+1
@@ -8,6 +8,7 @@
8 <meta name="format-detection" content="telephone=no" />
9 <meta name="robots" content="noindex,nofollow" />
10 <link type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS" />
11 + <link type="text/css" href="styles/custom.css" media="screen" rel="stylesheet" title="CSS" />
12 <link rel="apple-touch-icon" href="/favicon-303x303.png" />
13 <script type="text/javascript" src="scripts/common-0.0.1{{min}}.js"></script>
14 <title>Agent Installation</title>
views/login2.handlebars
+1
@@ -10,6 +10,7 @@
10 <link rel="manifest" href="{{{domainurl}}}manifest.json">
11 <link rel="shortcut icon" type="image/x-icon" href="{{{domainurl}}}favicon.ico" />
12 <link keeplink=1 type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS" />
13 + <link type="text/css" href="styles/custom.css" media="screen" rel="stylesheet" title="CSS" />
14 <link rel="apple-touch-icon" href="/favicon-303x303.png" />
15 <script type="text/javascript" src="scripts/common-0.0.1{{min}}.js"></script>
16 <script keeplink=1 type="text/javascript" src="scripts/u2f-api{{min}}.js"></script>
views/message2.handlebars
+1
@@ -8,6 +8,7 @@
8 <meta name=format-detection content="telephone=no" />
9 <meta name="robots" content="noindex,nofollow">
10 <link type=text/css href="/styles/style.css" media="screen" rel="stylesheet" title="CSS" />
11 + <link type="text/css" href="styles/custom.css" media="screen" rel="stylesheet" title="CSS" />
12 <link rel="apple-touch-icon" href="/favicon-303x303.png" />
13 <script type="text/javascript" src="scripts/common-0.0.1{{min}}.js"></script>
14 <title id="topTitle">{{{title1}}}</title>
views/messenger.handlebars
+1
@@ -9,6 +9,7 @@
9 <meta name="robots" content="noindex,nofollow">
10 <link type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS" />
11 <link type="text/css" href="styles/messenger.css" media="screen" rel="stylesheet" title="CSS" />
12 + <link type="text/css" href="styles/custom.css" media="screen" rel="stylesheet" title="CSS" />
13 <link rel="apple-touch-icon" href="/favicon-303x303.png" />
14 <script type="text/javascript" src="scripts/common-0.0.1{{min}}.js"></script>
15 <script type="text/javascript" src="scripts/filesaver.min.js"></script>
views/player.handlebars
+1
@@ -9,6 +9,7 @@
9 <meta name="robots" content="noindex,nofollow">
10 <link type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS" />
11 <link type="text/css" href="styles/xterm.css" media="screen" rel="stylesheet" title="CSS" />
12 + <link type="text/css" href="styles/custom.css" media="screen" rel="stylesheet" title="CSS" />
13 <link rel="apple-touch-icon" href="/favicon-303x303.png" />
14 <script type="text/javascript" src="scripts/common-0.0.1{{min}}.js"></script>
15 <script type="text/javascript" src="scripts/agent-desktop-0.0.2{{min}}.js"></script>
views/sharing.handlebars
+1
@@ -10,6 +10,7 @@
10 <link type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS" />
11 <link type="text/css" href="styles/style-sharing.css" media="screen" rel="stylesheet" title="CSS" />
12 <link type="text/css" href="styles/xterm.css" media="screen" rel="stylesheet" title="CSS" />
13 + <link type="text/css" href="styles/custom.css" media="screen" rel="stylesheet" title="CSS" />
14 <link rel="apple-touch-icon" href="/favicon-303x303.png" />
15 <script type="text/javascript" src="scripts/common-0.0.1{{min}}.js"></script>
16 <script type="text/javascript" src="scripts/amt-redir-ws-0.1.0{{{min}}}.js"></script>