Migrating DB1 to DB2: Lessons learned

I have finally migrated my Dashboards (DB1) to the new dashboard (DB2). The whole process took about 2 weeks for approximately nine dashboard pages (not complex pages, almost no CSS/custom styling, a few cases of ui_template/chart.js). I don’t have a background in coding but do have some understanding of coding languages and structuring logic, so if you are like me, I hope this is helpful. If you are an expert coder and familiar with javascript, Vue, CSS etc, this should be a simple process.

Getting started:

  1. Do read the documentation for Flowfuse/Dashboard (aka Dashboard 2) at Flowfuse Dashboard Docs - it lays out the new dashboard structure and the available widgets.
  2. Use the migration service to migrate your old dashboard flows. The big advantage is that it will automatically create the dashboard stucture (adding in ui-base, ui-page(s) etc.)
  3. One big change is in page layouts. In DB1, all pages were fixed layout but in DB2 there are multiple layout options (including fixed). I can’t remember if the migration service brings the pages over as “fixed” or “grid” but new pages default to “grid”. This can create issues in how the page layout appears, so something to be aware of See this discussion.
  4. The migration service converts some of the DB1 widgets into the equivalent in DB2 and disables others that do not have a direct replacement. However, you will still have to go edit the ones that have been migrated over since there are quite a few differences in how data is now input (e.g {{msg.payload}} has to be replaced by msg.payload)
  5. In DB1, I was using the “Dark theme” and there is no equivalent in DB2. I got close to it by creating a custom theme and then some CSS to the pages to look close to something I was happy with. See this discussion for custom themes in DB2

Specific migration tips/challenges:

These are based on my experience and only covers the widgets that I am using.

  1. ui_control: there is a new ui-control version that has similar functionality and the old one does not work. The new ui-control also has additional functionality that I am not using but my old code to show/hide widgets on a page worked with no modifications. In most other cases, I am using ui-control to initialize values on startup or to determine when a user has changed tabs and while I had to re-wire some flows, the widget works exactly like the one in DB1.
  2. ui_text: incoming value must be in msg.payload and any formatting (prefix/suffix) needs to be done prior to being received (cannot do it in widget configuration). To update labels, the inbound message should contain msg.ui_update.label with the updated label. You can also override the font, size, color of each ui-text widget but if you want to apply the same change to multiples ui-text widgets, you have to do it via CSS.
  3. ui_dropdown: Automatically converted to ui-dropdown in the migration sevice, I had to make no changes here.
  4. ui_datepicker: The “date picker” functionality is now built in to the ui-text-input widget and will need to be manually configured. I seem to recall that the incoming date (if you wanted to set a default date), had to be in a particular format (I do know that “2025-08-13” type format works)
  5. ui_gauge: I think this was also automatically migrated and are a little more versatile. I did have challenges getting them to display in a small size. One option for custom gauges specifically for DB2 is n this discussion.
  6. ui_table: The DB2 version of ui-table is brand new but you would need to revisit your logic. You also have a lot less control over how the data is displayed (without using custom CSS). I chose to use ui-tablulator by @omrid as it is based on the same Tabulator APIs as DB1 ui_table. However, the Tabulator APIs have changed (currently v4 - old one was v2 I think), so do need a little bit of work but your table layout definition can be easily adapted (watch out for date/time formatters). Also, you cannot send in your table data in msg.payload format but all now uses a pair (msg.tblCmd = “updateData”, msg.tbArgs = [your data1, your data2…..]). There is an excellent set of sample flows that are available, so you may want to look at those to get an idea of the changes required.
  7. ui_template+chart.js: This was probably my biggest pain point. I have several charts in DB1 that were mixed (bar+line or stacked). Getting them to work in DB2 was painful, but that was mainly due to my lack of familiarity with the Vue platform and the changes between Chart.js v2 and v4. I was finally able to get it to work thanks for members of this community (and ChartGPT!). Once one flow was working, I was able to adapt it for others and I decided to migrate all my charts to this solution (line, pie, bar+line, stacked). For a working sample see this discussion.

Miscellaneous:

I used ChatGPT to help with migrating my initial ui-template for a chart (chart.js). While ChartGPT was helpful I realized that it could be incredibly dumb. For example, it insisted on giving code that would work in DB1 and I finally got familiar enough with it to point out that the code I was getting back would not work in DB2. It would then give me the “updated” code but it took almost a week of back and forth to get it to a semi-working state. What really got me over the finish line were people in this community so :folded_hands:t3: to them.

What ChartGPT was immensely helpful with was checking for and catching syntax errors (missing “)”, “}”, “]” etc.), It was also helpful in catching misplaced sections of code and suggesting ways to simplify and eliminate redundant code. However, occasionally it would slip and mix DB1 and DB2 ui_template/ui-template code causing me to retrace many steps.

Also, I had to be pretty specific in the prompt “Check this Dashboard 2 (Flowfuse) ui-template code for Node-RED to do….”. Without “Flowfuse”, “Dashboard2” it would almost always give code that was for DB1.

Thanks for reading. Hopefully, this will make someone else’s path less painful.

6 Likes