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

If you need some help to begin with your first Dashboard Studio, feel free to ask. Maybe I or others can help.

The first post in this topic is a good one to start with, and have a look at the demo version and documentation in the latest version of Dashboard Studio.

The first steps will not be very easy, but when you start to understand it better you will proceed quicker and also discover the huge amount of ways to personalize your dashboard. Enjoy setting it up!

Small question:

The Horizontal line you get in the new text-widget (WOW, btw :wink: )when you type - - - , where does it inherit it’s color?

It’s a blue-like shadowed line, but no matter which blue color I change in the overal settings or in the text-widget settings: it stays the same…

Separate the command from the status feedback

Donation made in recognition of your outstanding work ! :slight_smile:

I hope I’m posting this in the right place…

I’d like to decouple the command (Homey virtual device) from the status feedback (Homey read-only Boolean variable).

I’d like the ON icon to be in a contrasting color (e.g., dark orange) if the variable is TRUE, and in the inverse color (light orange) if the variable is FALSE.

What’s the easiest way to do this? Sorry if this has already been discussed, but I couldn’t find anything specific.

Hello

I don’t see any widget that allows you to dynamically control a set of devices. Light style, shutters, fans… did I miss something

Sorry, I was trying to figure out something complicated last night when all I had to do was manage the STATE by linking it to my homey variable :slight_smile:

(and handle the icon selection too) :slight_smile:

image
Nice solution. I do get the impression that the column widths aren’t exactly pixels, but rather ratios between the columns.

What is the meaning of the Vertical spacing and Vertical alignment setting in the Text widget? Without an image in the table, there is no effect visible.

This is my result (I didn’t use an image in the table, because otherwise they would become too small)


Could the (Source/Bron) link open a new form? Now it opens in the same form as the DS app. When one returns from the linked URL back to the DS app, it opens the default DS page and not the page from which you started the link. Using Fully kiosk browser on Android tablet.

Great performance again!

I have noticed something unusual (I don’t know if this is related to this version, or earlier ):
I have an image with a transparent button on top of it with the same dimensions and a higher Z-value. When I press that button, a flow causes dimensions to change via variables. The image and the button use the same dimension variables. However, the button is now one click behind (and therefore has the previous dimensions).

If I then switch back to developer mode, the button does display the correct dimensions that are equal to the image (I have temporarily given the button a semi-transparent color). App restart did not solve this.

EDIT: the same for a toggle button/switch setting a local variable to hide/show other objects; these objects don’t become visible anymore.

Hi Satoer, I am doing some testing with the Markdown option. Now I want to create a weather forecast with 4 columns next to each other. I let a Homey script fetch the data and write it in Markdown format to a Homey variable. I actually want to use the moving icons from Bas Milius. With the example below, they also appear, but they are displayed too large. Can I adjust the size of the icons in another way?

Sorry @Satoer
I’m revisiting my post because I’ve noticed that the update for my button icon isn’t working reliably.

Even if I create a variable (ambiance.salon.status), send it to Dash via a flow, and assign it to STATE (ON/OFF), my button doesn’t reflect the variable’s actual state. Do you know why?

Thanks for your help…

Something like this? I can use it myself.


My hints:

  • define an extra dummy column at the end (not necessary)
  • use this column setting (5th is dummy):
  • use columns style ā€œColumn zebraā€
  • make your text object narrower (in my example 400 px)

@Amersfoort ,
Thank you for your help, that’s exactly what I meant!

Thanks :smiling_face: :clinking_beer_mugs:
Appreciate it!

I am trying to figure out what exactly you are trying to do. First let me get some semantics right:
A variable is a small piece of memory where you write boolean (true / false), numbers or strings to.
A Topic is the way Dashboard studio communicates with homey. A topic has a name and a value. You can send values over topics with the Send Card:

But you can also send capabilities from devices directly in the configuration:

You can also send Homey Variables directly from the same location.

How do you create this variable? And what does this ā€œstatusā€ contain? Is this a boolean value (true / false) Can you send some screenshots what you are trying to do? (Shift + Win + S if you are on windows)

This code has the same result, but shorter:

| **Din** | **Woe** | **Don** | **Vri** |
| :---: | :---: | :---: | :---: |
| ![icon](https://raw.githubusercontent.com/basmilius/weather-icons/dev/production/fill/svg/overcast.svg)**18°C**<br>12°C<br> šŸ’§ 0%<br>šŸ’Ø 25 km/u | ![icon](https://raw.githubusercontent.com/basmilius/weather-icons/dev/production/fill/svg/clear-day.svg)**16°C**<br>6°C<br> šŸ’§ 0%<br>šŸ’Ø 24 km/u | ![icon](https://raw.githubusercontent.com/basmilius/weather-icons/dev/production/fill/svg/clear-day.svg)**18°C**<br>6°C<br> šŸ’§ 0%<br>šŸ’Ø 22 km/u | ![icon](https://raw.githubusercontent.com/basmilius/weather-icons/dev/production/fill/svg/clear-day.svg)**22°C**<br>7°C<br> šŸ’§ 0%<br>šŸ’Ø 16 km/u |

Please share other ideas.

I have adjusted my Homey script and now it works like a charm :sun:. I will share my ideas with you :wink:

Okay, I think you misunderstood the philosophy of Dashboard studio. There are no device specific widgets. Dashboard studio consist out of building blocks so you can easily build your dashboard yourself exactly how you would like it. For example I just build your above example in like 10 minutes by combining a container widget, an icon widget and the new text widget. I created one, grouped it, duplicated it 6 times and changed them:

If you style them using the main default settings, all of the cards style identically.
In this example I only made the Climate card dynamic, and put a couple of sliders below it to adjust them. These are connected with local topics, but you can control the values just as easy from Homey.

You can import the following snippet (make sure you are on the latest 1.8.1 test build) to play with it yourself:

{
  "snippetHeader": "Dashboard Studio Snippet",
  "snippetType": "widget-snippet",
  "snippetFormatVersion": 1,
  "version": "1.8.1",
  "source": {
    "dashboardName": "Demo-cards",
    "page": 1,
    "createdAt": "2026-04-28T13:34:51.757Z"
  },
  "master": {
    "currentPage": 1
  },
  "widgets": {
    "slider_0326": {
      "type": "slider",
      "overrides": {
        "x": 100,
        "y": 510,
        "width": 270,
        "height": 80,
        "page": 1,
        "value": 23.8,
        "min": -20,
        "max": 40,
        "allowDecimals": true,
        "sendValueMode": "movement",
        "outputTopic": "local/temperature",
        "label": "RƩgler la tempƩrature",
        "metaName": "New Slider",
        "bgVisible": true
      },
      "bindings": {}
    },
    "slider_4240603": {
      "type": "slider",
      "overrides": {
        "x": 380,
        "y": 510,
        "width": 270,
        "height": 80,
        "page": 1,
        "value": 30,
        "allowDecimals": false,
        "sendValueMode": "movement",
        "outputTopic": "local/humidity",
        "label": "RƩgler l'humiditƩ",
        "metaName": "New Slider (Copy)",
        "bgVisible": true
      },
      "bindings": {}
    }
  },
  "groups": {
    "group_moin52e5_546": {
      "id": "group_moin52e5_546",
      "name": "Card",
      "locked": false,
      "visible": true,
      "bindings": {},
      "overridePage": "",
      "dimBackgroundWhenVisible": false,
      "widgets": {
        "empty_6100": {
          "type": "empty",
          "overrides": {
            "x": 100,
            "y": 180,
            "width": 270,
            "height": 70,
            "page": 1,
            "label": "",
            "metaName": "New Container"
          },
          "bindings": {}
        },
        "text_8865": {
          "type": "text",
          "overrides": {
            "x": 150,
            "y": 180,
            "width": 180,
            "height": 70,
            "page": 1,
            "text": "# Lumieres\nTout eteint",
            "typography": {
              "mdParagraph": {
                "fontSize": 17
              },
              "mdH1": {
                "fontSize": 20
              },
              "mdH2": {},
              "mdH3": {},
              "mdTh": {},
              "mdTableText": {}
            },
            "metaName": "New Text",
            "cornerRadius": 0,
            "mdBlockSpacing": -5,
            "bgVisible": false
          },
          "bindings": {}
        },
        "icon_4342": {
          "type": "icon",
          "overrides": {
            "x": 110,
            "y": 180,
            "width": 50,
            "height": 70,
            "page": 1,
            "icon": "ph-lightbulb",
            "metaName": "New Icon",
            "size": 35,
            "colInactive": "@textMuted",
            "colActive": "@warning",
            "bgVisible": false
          },
          "bindings": {}
        }
      }
    },
    "group_moin58jz_ma": {
      "id": "group_moin58jz_ma",
      "name": "Card (Copy)",
      "locked": false,
      "visible": true,
      "bindings": {},
      "overridePage": "",
      "dimBackgroundWhenVisible": false,
      "widgets": {
        "empty_2871800": {
          "type": "empty",
          "overrides": {
            "x": 100,
            "y": 260,
            "width": 270,
            "height": 70,
            "page": 1,
            "label": "",
            "metaName": "New Container (Copy)"
          },
          "bindings": {}
        },
        "text_2873996": {
          "type": "text",
          "overrides": {
            "x": 150,
            "y": 260,
            "width": 200,
            "height": 70,
            "page": 1,
            "text": "# Haut-parleurs\nTout en pause",
            "typography": {
              "mdParagraph": {
                "fontSize": 17
              },
              "mdH1": {
                "fontSize": 20
              },
              "mdH2": {},
              "mdH3": {},
              "mdTh": {},
              "mdTableText": {}
            },
            "metaName": "New Text (Copy)",
            "cornerRadius": 0,
            "mdBlockSpacing": -5,
            "bgVisible": false
          },
          "bindings": {}
        },
        "icon_2877354": {
          "type": "icon",
          "overrides": {
            "x": 110,
            "y": 260,
            "width": 50,
            "height": 70,
            "page": 1,
            "icon": "ph-music-note-simple",
            "metaName": "New Icon (Copy)",
            "size": 35,
            "colInactive": "@textMuted",
            "colActive": "@warning",
            "bgVisible": false
          },
          "bindings": {}
        }
      }
    },
    "group_moin5amv_559": {
      "id": "group_moin5amv_559",
      "name": "Card (Copy) (Copy)",
      "locked": false,
      "visible": true,
      "bindings": {},
      "overridePage": "",
      "dimBackgroundWhenVisible": false,
      "widgets": {
        "empty_5570172": {
          "type": "empty",
          "overrides": {
            "x": 100,
            "y": 340,
            "width": 270,
            "height": 70,
            "page": 1,
            "label": "",
            "metaName": "New Container (Copy) (Copy)"
          },
          "bindings": {}
        },
        "text_557168": {
          "type": "text",
          "overrides": {
            "x": 150,
            "y": 340,
            "width": 180,
            "height": 70,
            "page": 1,
            "text": "# Climate\n{{local/temperature}}° | {{local/humidity}}%",
            "typography": {
              "mdParagraph": {
                "fontSize": 17
              },
              "mdH1": {
                "fontSize": 20
              },
              "mdH2": {},
              "mdH3": {},
              "mdTh": {},
              "mdTableText": {}
            },
            "metaName": "New Text (Copy) (Copy)",
            "cornerRadius": 0,
            "mdBlockSpacing": -5,
            "bgVisible": false
          },
          "bindings": {}
        },
        "icon_5574151": {
          "type": "icon",
          "overrides": {
            "x": 110,
            "y": 340,
            "width": 50,
            "height": 70,
            "page": 1,
            "icon": "ph-thermometer-simple",
            "active": true,
            "metaName": "New Icon (Copy) (Copy)",
            "size": 35,
            "colInactive": "@textMuted",
            "colActive": "@warning",
            "bgVisible": false
          },
          "bindings": {}
        }
      }
    },
    "group_moin5csj_5ue": {
      "id": "group_moin5csj_5ue",
      "name": "Card (Copy) (Copy) (Copy)",
      "locked": false,
      "visible": true,
      "bindings": {},
      "overridePage": "",
      "dimBackgroundWhenVisible": false,
      "widgets": {
        "empty_8366536": {
          "type": "empty",
          "overrides": {
            "x": 380,
            "y": 180,
            "width": 270,
            "height": 70,
            "page": 1,
            "label": "",
            "metaName": "New Container (Copy) (Copy) (Copy)"
          },
          "bindings": {}
        },
        "text_8368796": {
          "type": "text",
          "overrides": {
            "x": 430,
            "y": 180,
            "width": 180,
            "height": 70,
            "page": 1,
            "text": "# Active\nActif",
            "typography": {
              "mdParagraph": {
                "fontSize": 17
              },
              "mdH1": {
                "fontSize": 20
              },
              "mdH2": {},
              "mdH3": {},
              "mdTh": {},
              "mdTableText": {}
            },
            "metaName": "New Text (Copy) (Copy) (Copy)",
            "cornerRadius": 0,
            "mdBlockSpacing": -5,
            "bgVisible": false
          },
          "bindings": {}
        },
        "icon_8370521": {
          "type": "icon",
          "overrides": {
            "x": 390,
            "y": 180,
            "width": 50,
            "height": 70,
            "page": 1,
            "icon": "ph-person-simple-run",
            "active": true,
            "metaName": "New Icon (Copy) (Copy) (Copy)",
            "size": 35,
            "colInactive": "@textMuted",
            "colActive": "@accentSoft",
            "bgVisible": false,
            "blink": false
          },
          "bindings": {}
        }
      }
    },
    "group_moin5fqe_6hz": {
      "id": "group_moin5fqe_6hz",
      "name": "Card (Copy) (Copy) (Copy) (Copy)",
      "locked": false,
      "visible": true,
      "bindings": {},
      "overridePage": "",
      "dimBackgroundWhenVisible": false,
      "widgets": {
        "empty_2177820": {
          "type": "empty",
          "overrides": {
            "x": 380,
            "y": 260,
            "width": 270,
            "height": 70,
            "page": 1,
            "label": "",
            "metaName": "New Container (Copy) (Copy) (Copy) (Copy)"
          },
          "bindings": {}
        },
        "text_2179607": {
          "type": "text",
          "overrides": {
            "x": 430,
            "y": 260,
            "width": 180,
            "height": 70,
            "page": 1,
            "text": "# Lumieres\nTout eteint",
            "typography": {
              "mdParagraph": {
                "fontSize": 17
              },
              "mdH1": {
                "fontSize": 20
              },
              "mdH2": {},
              "mdH3": {},
              "mdTh": {},
              "mdTableText": {}
            },
            "metaName": "New Text (Copy) (Copy) (Copy) (Copy)",
            "cornerRadius": 0,
            "mdBlockSpacing": -5,
            "bgVisible": false
          },
          "bindings": {}
        },
        "icon_2181729": {
          "type": "icon",
          "overrides": {
            "x": 390,
            "y": 260,
            "width": 50,
            "height": 70,
            "page": 1,
            "icon": "ph-leaf",
            "active": true,
            "metaName": "New Icon (Copy) (Copy) (Copy) (Copy)",
            "size": 35,
            "colInactive": "@textMuted",
            "colActive": "#139E06",
            "bgVisible": false
          },
          "bindings": {}
        }
      }
    },
    "group_moin5h1r_ic": {
      "id": "group_moin5h1r_ic",
      "name": "Card (Copy) (Copy) (Copy) (Copy) (Copy)",
      "locked": false,
      "visible": true,
      "bindings": {},
      "overridePage": "",
      "dimBackgroundWhenVisible": false,
      "widgets": {
        "empty_3880521": {
          "type": "empty",
          "overrides": {
            "x": 380,
            "y": 340,
            "width": 270,
            "height": 70,
            "page": 1,
            "label": "",
            "metaName": "New Container (Copy) (Copy) (Copy) (Copy) (Copy)"
          },
          "bindings": {}
        },
        "text_3882174": {
          "type": "text",
          "overrides": {
            "x": 430,
            "y": 340,
            "width": 260,
            "height": 70,
            "page": 1,
            "text": "# Batteries\nTout fonctionne corr...",
            "typography": {
              "mdParagraph": {
                "fontSize": 17
              },
              "mdH1": {
                "fontSize": 20
              },
              "mdH2": {},
              "mdH3": {},
              "mdTh": {},
              "mdTableText": {}
            },
            "metaName": "New Text (Copy) (Copy) (Copy) (Copy) (Copy)",
            "cornerRadius": 0,
            "mdBlockSpacing": -5,
            "bgVisible": false
          },
          "bindings": {}
        },
        "icon_3886580": {
          "type": "icon",
          "overrides": {
            "x": 390,
            "y": 340,
            "width": 50,
            "height": 70,
            "page": 1,
            "icon": "ph-battery-high",
            "active": true,
            "metaName": "New Icon (Copy) (Copy) (Copy) (Copy) (Copy)",
            "size": 35,
            "colInactive": "@textMuted",
            "colActive": "#139E06",
            "bgVisible": false
          },
          "bindings": {}
        }
      }
    }
  }
}

Ah yes. It uses the theme border color:

But it does not have a separate custom setting inside the widget itself. I think I shall link it to the ā€œTable Border Colorā€ in a follow up version. Or do you think a real separate ā€œHorizontal rule colorā€ setting for this is preferable?

Left vertical alignment set to bottom with a ā€œ3ā€ vertical spacing . Right vertical alignment set to top with a ā€œ21ā€ vertical spacing

It should be pixels though. Text does not get masked of by the borders though, so that spills over.

good point. It should open a new tab, just like the button does.

:slightly_smiling_face:

… and this happens, when Jupiter aligns with Mars and the room temperature is exactly 12 degrees… You always seem to find the weirdest edge cases :rofl: . I shall look into this.

No in terms of design that’s not the problem, I see that you have to do everything manually, but the dynamic is to display by clicking on ā€œlightā€ the lights that are on, because otherwise you would have to create 30 lights in terms of design to display only the lights on. it has to be a summary.

Thanks for your answer

I think I’ve figured out the problem. My Homey is set to French. I need to force the value to 1 or 0 instead of the value returned by my flow. Then I update the linked variable in the Dash.

And now it works ! But maybe you could make it so that it works regardless of the language?

I hope that makes sense :slight_smile:

Aha, yes, that’s the one.

I think any (table-related) color you can change IN the widget settings would make sense…

A new issue has popped up over here when trying out the Calendar-stuff.

One Google Calender : works fine.

2 Google Calendars, however, crashes dashboard Studio at the moment where the ā€˜Combined Ical Data’ is sent to the Dashboard.