[APP][Pro] Dashboard Studio - A completely free-form dashboard designer

I’m sure this simple dashboard is not what you advanced-users are waiting for, but this now gives me all the info I need in the wink of an eye. Resolution is fitted for an older Samsung 7" tablet.

On top the +/- realtime data from Solar Panels, Grid, Home-batteries, gas and the car. Tapping (clicking) in this area gives you additional data as seen in the smaller screenshot: Collected kWh out of the sun for today & yesterday, returned power to the grid for today (calculated every 15’) and yesterday, last update of the batteries (too verify they’re still online, only updates when battery % changes), total gas used for today.
The different flow colors and directions are changed based on the actual status. Batteries in standby = white line, no solar power = white line, car charging = blue line and fille car-icon, which also doubles as a switch to start/stop charging, no gas used today = white line: but that almost never happens since hot water is gas-based here… Grid flow is red/white/green and direction is changed also

Next is simply the different thermometers in house and on the in-wall terrace (left above the clock)

The bullet on the bottom of the clock-frame is the volume-slider for the Yamaha just below.

All the other little frames are switches, the orange one changes color together with the actual lamp based on excess-solar-energy and the status of the washing machine.

On the left side just icons (some of which are self-drawn SVG images) reflecting the status of door/window-sensors, washing-machine (blue = running, green=ready) & garden-irrigation (green = need for irrigation, blue = running, red is STILL running)

Then there is the actual weather (ph-icon dictated by a flow), forecast today & tomorrow (based on home made script using open Meteo).
The ‘last updates’ for the things I think are important to me. (It’s a list-widget which reads a Homey Variable(JSON). The variable is filled with a HomeyScript that adds the latest messages to the variable and keeps the 15 latest items. This way all info is still there after a reboot, update,…)

The newest addition is the calendar, which is still running using my own script to parse the data in a Markdown-view.

Thanks for sharing your dashboard and the detailed explanation, @Bert_Onraedt !
It’s nice to see what someone else has made of it. In this case, a sleek and clear dashboard with all information and controls at a glance. The energy flows, in particular, look good.

I have looked into this but it probably cannot be done on modern browsers. A website or JavaScript cannot close a webpage unless it was opened by the same script which is not the case here. Since Dashboard studio is basically a website it does not have the privileges to close itself. There is a JavaScript instruction you could try with a button using the On click setting to Open URL and use:

javascript:window.close();

Inside the Target URL. Maybe you will have luck with Fully Kiosk since I have not tried it and this browser might accept this. I have personally tried it without any luck in Firefox and Chrome.

[edit]
Workaround: If this does not work. You could try to interface with kiosk browser directly using the Remote Administration API. This has the ability to move the kiosk browser to the background.
So: Button that sends a message to a homey flow. The homey flow triggers and sends a close command to the kiosk browser.

I have not dived deeper into this, it is a bit out of the scope of DS. I am sure AI can help you much better than I can with this :sweat_smile:

NEW TEST version 1.9.5:

  • New: Edit box widget - Send Behavior can send when you press Enter or when you leave the field (Keyboard Enter & Exit).
  • New: Switch and Button widget - Text Only and Invisible visual styles in the Visual Style dropdown.
  • Fixed: Switch and Button widget - the pointing-hand cursor appears only over the button area, not the full widget container.
  • Improved: Text widget - markdown tables with a fully empty header row no longer render a visible header; only the body rows are shown.
  • Improved: Switch and Menu widgets - optional New tab setting opens the target URL in a new browser tab when On Click is Open URL.
  • Improved: Switch and Menu widgets - you can now use the website favicon as the icon when On Click is Open URL and a Target URL is set.
  • New: Menu widget - Layout Direction: Horizontal & Vertical “Grid” layout.

Button Widget:

The button widget now has two new visual styles. Text only and invisible:

In invisible mode you still see a blue outline in edit mode (otherwise it is invisible… duh)

This is fixed. The hand only shows on the actual button area now.

Also added: when “Open URL” is selected in “On Click” of a Switch or menu item widget, and an external URL is set, it is now possible to choose the favicon (this is the website icon) in the icon settings:

This is a personal request. I would like to create a default browser homepage with Dashboard Studio. This way I can navigate easily to other sites with a list of links and control my home. It is still a work in progress. Dashboard Studio is specifically aimed at pixel perfect alignment and fixed resolutions. For this to become the home page it needs to be responsive so it adapts to different browser window sizes.

Also new in the menu widget: Layout Direction: Horizontal & Vertical “Grid” layout.

This way you can create a grid of icons.

Text Widget:

Markdown tables with empty headers are now collapsed / not rendered.

Edit box Widget:

The edit box now has a “Keyboard (enter) & Exit” Send behavior added.

In this mode the contents of the edit box gets also send when the user tabbed out of the edit box.
Note: It is still mandatory to create the edit boxes in order of tabbing.

Happy to report that this works like a charm

Nice!
You can also create a graph of that same variable value inside dashboard studio with this card:

And put the topic inside the data setting of a graph widget.

Interesting, are you using the “Light Grid” widget to control heating? Or did you just mimic the design with separate widget elements like a container, icon and switch?

There is even a dedicated app for that browser:

Maybe this works?

(Just trigger it with a topic)

Yes I am using Light Grid but looking to change lightning and heating to buttons only

But is it working? Or did you just add it as a mock-up? Because the light-grid sends “Unified Light State (JSON)” in the topic (See help file). Not just true or false. It can be done, but then you have to parse the json manually in a homey flow.

Yes working for me like a normal button. Mapped it to a smart plug on/off command.

Funny, never intended that usage for it :sweat_smile:. I did not expect to work.

Thank you for all the improvements!

Fully Kiosk, the full (paid) version, requires (too) many Android authorizations, but needed for the Dashboard Controller app. I have tried a lot of alternatives to close the DS app (not the tablet screen) with a Dash button. I succeeded with the Android app Macrodroid, but then Fully Kiosk could not be started up normally again.

Now I only use an mm-wave sensor and Macrodroid to turn the tablet screen on or off via webhooks.

I have created a dialog box that confirms that something can be removed. This is a group containing:

  • a blurred background image
  • a label with a question
  • a ‘No’ button
  • a ‘Yes’ button

The ‘Yes’ button has the same Z-value as the ‘No’ button. When the group option “Blur background when visible” is enabled, the ‘No’ button appears in the background (or so it seems)


When this option is disabled, it looks as expected:

Something I can do to improve?

Snippet code group:

{
  "snippetHeader": "Dashboard Studio Snippet",
  "snippetType": "widget-snippet",
  "snippetFormatVersion": 1,
  "version": "1.9.5",
  "source": {
    "dashboardName": "HomeDashV2",
    "page": 25,
    "createdAt": "2026-06-04T06:18:33.361Z"
  },
  "master": {
    "currentPage": 25
  },
  "widgets": {},
  "groups": {
    "group_mpz3qm5r_105": {
      "id": "group_mpz3qm5r_105",
      "name": "Group 12",
      "locked": false,
      "visible": false,
      "bindings": {
        "visible": "homey/event/toonVerwijderDialog"
      },
      "overridePage": "",
      "dimBackgroundWhenVisible": true,
      "widgets": {
        "switch_460485110": {
          "type": "switch",
          "overrides": {
            "x": 1270,
            "y": 970,
            "width": 150,
            "height": 80,
            "zIndex": 42,
            "page": "25",
            "buttonLabel": "Nee",
            "outputTopic": "toonVerwijderDialog",
            "onPayload": "false",
            "icons": {
              "on": {
                "source": "custom",
                "builtin": "ph-check-fat",
                "weight": "regular",
                "customUrl": "https://cdn.jsdelivr.net/npm/@mdi/svg@7.2.96/svg/close-thick.svg",
                "tintImage": true,
                "color": "#1D4ED8",
                "size": 15
              },
              "off": {
                "color": "#1D4ED8",
                "size": 15,
                "offsetX": 0,
                "offsetY": 0,
                "tintImage": true
              }
            },
            "iconColorOverrides": {
              "on": {
                "enabled": false,
                "color": "#ffffff"
              },
              "off": {
                "enabled": false,
                "color": "#94a3b8"
              }
            },
            "style": "button",
            "labelPos": "inside_right",
            "showIcon": true,
            "bevel": true,
            "btnGlow": false,
            "metaName": "Sluiten Setup",
            "colOn": "#E2E8F0",
            "colOff": "#E2E8F0",
            "bgVisible": true,
            "bgColStart": "#E2E8F0",
            "bgColEnd": "#E2E8F0",
            "bgOpacityStart": 100,
            "borderColor": "#006aff",
            "borderWidth": 0,
            "visible": true,
            "typography": {
              "buttonLabelOutside": {
                "fontSize": 25,
                "color": "#ffffff",
                "colorOff": "#ffffff",
                "textTransform": "none"
              },
              "buttonLabelInside": {
                "fontSize": 35,
                "color": "#1D4ED8",
                "colorOff": "#1D4ED8",
                "textTransform": "none",
                "fontFamily": "'Exo 2', sans-serif",
                "textAlign": "center"
              }
            },
            "_switchTypographyV2": true,
            "mode": "push",
            "_switchIconsV3": true
          },
          "bindings": {}
        },
        "switch_594096916": {
          "type": "switch",
          "overrides": {
            "x": 1450,
            "y": 970,
            "width": 150,
            "height": 80,
            "zIndex": 42,
            "page": "25",
            "buttonLabel": "Ja",
            "outputTopic": "SolarRegelVerwijderen",
            "icons": {
              "on": {
                "source": "custom",
                "builtin": "ph-check-fat",
                "weight": "regular",
                "customUrl": "https://cdn.jsdelivr.net/npm/@mdi/svg@7.2.96/svg/check-bold.svg",
                "tintImage": true,
                "color": "#E2E8F0",
                "size": 15
              },
              "off": {
                "color": "#E2E8F0",
                "size": 15,
                "offsetX": 0,
                "offsetY": 0,
                "tintImage": true
              }
            },
            "iconColorOverrides": {
              "on": {
                "enabled": false,
                "color": "#ffffff"
              },
              "off": {
                "enabled": false,
                "color": "#94a3b8"
              }
            },
            "style": "button",
            "labelPos": "inside_right",
            "showIcon": true,
            "bevel": true,
            "btnGlow": false,
            "metaName": "Sluiten Setup (Copy)",
            "colOn": "#0000ff",
            "colOff": "#0000ff",
            "bgVisible": true,
            "bgColStart": "#0062ff",
            "bgColEnd": "#004cff",
            "bgOpacityStart": 100,
            "borderColor": "#006aff",
            "borderWidth": 0,
            "visible": true,
            "typography": {
              "buttonLabelOutside": {
                "fontSize": 25,
                "color": "#ffffff",
                "colorOff": "#ffffff",
                "textTransform": "none"
              },
              "buttonLabelInside": {
                "fontSize": 35,
                "color": "#ffffff",
                "colorOff": "#ffffff",
                "textTransform": "none",
                "fontFamily": "'Exo 2', sans-serif",
                "textAlign": "center"
              }
            },
            "_switchTypographyV2": true,
            "mode": "push",
            "_switchIconsV3": true
          },
          "bindings": {}
        },
        "label_7407": {
          "type": "label",
          "overrides": {
            "x": 990,
            "y": 790,
            "width": 610,
            "height": 120,
            "zIndex": 42,
            "page": 25,
            "text": "Regel met de meest recente jaar/maand verwijderen? ",
            "labelWAuto": false,
            "labelHAuto": false,
            "typography": {
              "label": {
                "fontSize": 35
              }
            },
            "metaName": "New Label"
          },
          "bindings": {}
        },
        "image_597965412": {
          "type": "image",
          "overrides": {
            "x": 960,
            "y": 710,
            "width": 670,
            "height": 360,
            "zIndex": 39,
            "page": "25",
            "sourceType": "svg",
            "svgRaw": "<svg width=\"670\" height=\"360\" viewBox=\"0 0 670 360\" xmlns=\"http://www.w3.org/2000/svg\">\n  <foreignObject width=\"100%\" height=\"100%\">\n    <div xmlns=\"http://www.w3.org/1999/xhtml\" \n         style=\"\n            width: 100%;\n            height: 100%;\n            background: rgba(0, 0, 0, 0.4);\n            backdrop-filter: blur(15px);\n            -webkit-backdrop-filter: blur(15px);\n            /* border-radius: Zorgt voor de gevraagde afronding van 20px */\n            border-radius: 20px;\n            /* border: Voegt een doorlopende (solid) rand toe van 1px dik met een lichtoranje kleur (RGB met 0.6 transparantie voor een zachte uitstraling) */\n            border: 1px solid rgba(255, 179, 0, 0.3);\n            /* box-sizing: Zorgt ervoor dat de rand binnen de 100% breedte/hoogte valt en niet buiten de SVG snijdt */\n            box-sizing: border-box;\">\n    </div>\n  </foreignObject>\n</svg>\n",
            "metaName": "Dialog achtergrond",
            "bgVisible": true,
            "bgOpacityStart": 0,
            "bgOpacityEnd": 0,
            "glowEnabled": true,
            "glowOpacity": 100,
            "borderColor": "#ffb300",
            "visible": true,
            "borderWidth": 0,
            "cornerRadius": 20,
            "labelFs": 40,
            "labelOffY": 10,
            "glowColor": "#000000",
            "colOff": "#878787",
            "labelFont": "'Exo 2', sans-serif",
            "labelCol": "@surfaceHover",
            "opacity": 100,
            "fit": false,
            "proportional": false,
            "scale": 100,
            "borderOpacity": 60
          },
          "bindings": {}
        }
      }
    }
  }
}

I was breaking my head why the container blurred the background in edit mode. I did not recall that I build in any functionality that blurred the background of a container widget. Then I noticed it isn’t a container at all but an blurred svg in a image widget. Got to read better :sweat_smile:

I don’t know why it happens. The blur leaks out and traps elements layered right on top of it, while causing competing blurred backgrounds to glitch and fight for dominance.

But why are you doing it this way? The option “Blur Background When Visible” Already blurs the whole background behind the group.

You are right. I had already created a blurred background with an image when I saw that a group could blur the entire background.

Now that I have used a container, everything is displayed correctly.

For this graph. Is this flow on its own? just this card? and not sure how to put that in Data source

I have documented in the documentation how to feed insight data from Homey to a graph over here. :slightly_smiling_face:
You can find the topic in the data stream explorer:

Amazing, got that working. Graph is showing last 24h, is there a way to show only for the day? So from midnight and then populates for the rest of the day as it goes.

Another topic.

I have these 2 images on the dashboard. Idea is:

Left image is for Sonos. When music plays it displays album artwork, when music not playing it displays sonos logo. (Currently only have image placed as i seem to have no option to display artwork from sonos)

Right image is for Apple TV. When playing it displays artwork (this works) and when not playing should display Apple TV logo (currrently says no image available)

Am I looking for too much or is something like this possible?

Yes, I specifically added “today” for this reason. (This is not a native Homey selection option).

When used it is creating a full 24 hour graph of today (fromm 0:00 to 24:00), but populates the data for rest of the day as it goes.

This should be easily doable. But I do not have a clue how you are showing those sonos or Apple TV content. I assume you are providing links to those images from within a Homey flow.

Dashboard studio features a full Image Gallery browser / uploader:

You can upload any image here to use inside your widgets. Just click the copy button to grab the image URL.

As I mentioned, I am not entirely sure how your Sonos or Apple TV flows retrieve information, but you should definitely be able to detect when nothing is playing. When that happens, you can just use a DS card to send the URL of the image you uploaded to the gallery to the exact same topic that updates your album artwork widget.

If a Homey script is retrieving the images and you don’t know how to adjust it (for instance, if someone else wrote it), you could also check the output using this card:

afbeelding

I assume the album art comes from an external URL like http://apple.com/albumart/blabla. Just add a part of the URL that is always present into the value field. When there is no image, it probably won’t send a valid URL. This card will then switch to the false position, which you can connect to a DS card that sends the gallery image URL you uploaded. (do not forget to connect the true position to send the album art url like it does now)

NEW TEST Version 1.9.6/7

  • New: Image widget - Fallback URL shows a replacement image when the primary URL fails. Leave empty to show nothing.
  • New: Graph widget - Show Point Values displays data values directly next to the points or bars on the chart. Optionally on mouse hover only.
  • New: Text widget - color individual markdown table cells with [cell #hex] or [cell@themeToken at the start of a cell. The Full editor adds a cell background picker (and Clear) when the cursor is in a table cell.
  • Improved: Text widget - markdown code blocks have their own Code typography section (font, text and background colors, spacing, and line height).
  • Improved: Dashboard performance, especially in Google Chrome.

Image Widget:

The Image widget now features a “Fallback URL”

When an image is not available it show the Fallback image.
@Amersfoort If you leave this empty it should show nothing.
@Crazy_Avocado If you add your apple / sonos image in here it should show this placeholder if it your script sends an empty url (like no album art)

@Jos_Stultjens Please do not update to this version yet, It has some breaking changes with the image widget and it does not work any more on iOS 12. Luckily I still have the test device and will solve it in a next version.

Text Widget:

Cell coloring is now possible in a markdown grid! use [cell #hex] or [cell@themeToken] at the start of a cell.

Note: Performance may degrade when using a massive amount of cells

Also added font typography settings for code blocks (you can use it also to create “tag” like style formats inside your markdown)

Graph Widget

I have added this request. It is now possible to add datapoint values:

this setting:

It also has its own typography section to change the font / size offset etc.

This is now also possible:

When you set “Show on Hover” to “Enabled” it will only show the values above the bar where the mouse hovers above.