diff --git a/package-lock.json b/package-lock.json
index ad86bf3003dde2f11a241e276e0f8c9b5e854490..66f1ebdaaa44b08f77df9f9b71646bd166fb1959 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5563,9 +5563,9 @@
           }
         },
         "tar": {
-          "version": "6.1.0",
-          "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz",
-          "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==",
+          "version": "6.1.11",
+          "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
+          "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
           "requires": {
             "chownr": "^2.0.0",
             "fs-minipass": "^2.0.0",
@@ -9667,9 +9667,9 @@
           }
         },
         "tar": {
-          "version": "6.1.0",
-          "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz",
-          "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==",
+          "version": "6.1.11",
+          "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
+          "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
           "dev": true,
           "requires": {
             "chownr": "^2.0.0",
@@ -13139,9 +13139,9 @@
           }
         },
         "tar": {
-          "version": "6.1.0",
-          "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz",
-          "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==",
+          "version": "6.1.11",
+          "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
+          "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
           "dev": true,
           "requires": {
             "chownr": "^2.0.0",
@@ -20257,9 +20257,9 @@
       }
     },
     "jszip": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.6.0.tgz",
-      "integrity": "sha512-jgnQoG9LKnWO3mnVNBnfhkh0QknICd1FGSrXcgrl67zioyJ4wgx25o9ZqwNtrROSflGBCGYnJfjrIyRIby1OoQ==",
+      "version": "3.7.1",
+      "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.7.1.tgz",
+      "integrity": "sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg==",
       "dev": true,
       "requires": {
         "lie": "~3.3.0",
@@ -21576,9 +21576,9 @@
           }
         },
         "tar": {
-          "version": "6.1.0",
-          "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz",
-          "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==",
+          "version": "6.1.11",
+          "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
+          "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
           "dev": true,
           "requires": {
             "chownr": "^2.0.0",
@@ -22562,9 +22562,9 @@
       "dev": true
     },
     "path-parse": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
-      "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
       "dev": true
     },
     "path-to-regexp": {
@@ -26995,6 +26995,11 @@
       "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
       "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
     },
+    "toposort": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
+      "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA="
+    },
     "totalist": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz",
@@ -27697,9 +27702,9 @@
       }
     },
     "url-parse": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.1.tgz",
-      "integrity": "sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==",
+      "version": "1.5.3",
+      "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz",
+      "integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==",
       "dev": true,
       "requires": {
         "querystringify": "^2.1.1",
diff --git a/package.json b/package.json
index 0ab9d22dc08a626220a523d885764756a4c031c8..06c1c9ce756554aed7270a9f486f93427efcf9fd 100644
--- a/package.json
+++ b/package.json
@@ -102,6 +102,7 @@
     "request": "^2.88.2",
     "source-map-support": "^0.5.19",
     "sqlite3": "^5.0.2",
+    "toposort": "^2.0.2",
     "utf-8-validate": "^5.0.5",
     "uuid": "^8.3.2",
     "ws": "^7.5.2",
diff --git a/src-electron/db/query-zcl.js b/src-electron/db/query-zcl.js
index 536cae266cda0f3bedde83aced10d41ea1e8fce7..0aa2d95ae9ad721f211d9511f9b2f2b4dc03e3d4 100644
--- a/src-electron/db/query-zcl.js
+++ b/src-electron/db/query-zcl.js
@@ -206,6 +206,7 @@ async function selectAllStructsWithItems(db, packageId) {
       db,
       `
 SELECT
+  STRUCT.STRUCT_ID AS STRUCT_ID,
   STRUCT.NAME AS STRUCT_NAME,
   ITEM.NAME AS ITEM_NAME,
   ITEM.FIELD_IDENTIFIER AS ITEM_IDENTIFIER,
@@ -231,7 +232,9 @@ ORDER BY STRUCT.NAME, ITEM.FIELD_IDENTIFIER`,
         if (acc.length == 0 || acc[acc.length - 1].name != value.STRUCT_NAME) {
           // Create a new object
           objectToActOn = {
+            id: value.STRUCT_ID,
             name: value.STRUCT_NAME,
+            label: value.STRUCT_NAME,
             items: [],
           }
           acc.push(objectToActOn)
diff --git a/src-electron/generator/helper-zcl.js b/src-electron/generator/helper-zcl.js
index 6eecc6d8d45948f6c81c6b9d6acc45007d652a5c..0b3d117e5d080f231d55fc8acd47af60a997b59c 100644
--- a/src-electron/generator/helper-zcl.js
+++ b/src-electron/generator/helper-zcl.js
@@ -92,7 +92,7 @@ function zcl_structs(options) {
   let promise = templateUtil
     .ensureZclPackageId(this)
     .then((packageId) =>
-      queryZcl.selectAllStructsWithItemCount(this.global.db, packageId)
+      queryZcl.selectAllStructsWithItems(this.global.db, packageId)
     )
     .then((structs) => zclUtil.sortStructsByDependency(structs))
     .then((structs) => templateUtil.collectBlocks(structs, options, this))
diff --git a/src-electron/util/zcl-util.js b/src-electron/util/zcl-util.js
index 8f4d9d92e5decfa17c8a5a0f798c0ba5414f830c..02f0af592ec67917bb7553aca7ce25ca20de8345 100644
--- a/src-electron/util/zcl-util.js
+++ b/src-electron/util/zcl-util.js
@@ -20,6 +20,7 @@
  *
  * @module REST API: various zcl utilities
  */
+const toposort = require('toposort')
 
 /**
  * Comparator for sorting clusters.
@@ -69,16 +70,51 @@ function commandComparator(a, b) {
   return 0
 }
 
+function findStructByName(structs, name) {
+  for (const s of structs) {
+    if (s.name == name) {
+      return s
+    }
+  }
+  return null
+}
+
 /**
  * This method retrieves a bunch of structs sorted
  * alphabetically. It's expected to resort the structs into a list
  * where they are sorted in a way where dependency is observed.
  *
+ * It uses the DFS algorithm to traverse the DAG in a way the
+ * dependencies are observed.
+ *
  * @param {*} structs
  * @returns
  */
 async function sortStructsByDependency(structs) {
-  return structs
+  let allStructNames = structs.map((s) => s.name)
+  let edges = []
+
+  // Add edges
+  structs.forEach((s) => {
+    s.items.forEach((i) => {
+      const type = i.type
+      if (allStructNames.includes(type)) {
+        edges.push([s.name, type])
+      }
+    })
+  })
+
+  let sortedEdges = toposort(edges).reverse()
+
+  let finalSort = []
+  sortedEdges.forEach((s) => {
+    finalSort.push(findStructByName(structs, s))
+  })
+  allStructNames.forEach((s) => {
+    if (!sortedEdges.includes(s)) finalSort.push(findStructByName(structs, s))
+  })
+
+  return finalSort
 }
 
 exports.clusterComparator = clusterComparator
diff --git a/test/resource/meta/types.xml b/test/resource/meta/types.xml
index fd8e872517b8c4b1c12a40769ead9f87682bb917..86d2c82c8e110108fc53f1418f7546a5b3e94aaa 100644
--- a/test/resource/meta/types.xml
+++ b/test/resource/meta/types.xml
@@ -86,4 +86,21 @@ limitations under the License.
     <item name="b" type="BOOLEAN" optional="false"/>
     <item name="c" type="SimpleStruct" optional="false"/>
    </struct>
+
+   <struct name="A">
+     <item name="x" type="UINT8U"/>
+     <item name="b" type="B"/>
+     <item name="c" type="C"/>
+   </struct>
+   <struct name="B">
+     <item name="x" type="UINT8U"/>
+     <item name="d" type="D"/>
+   </struct>
+   <struct name="C">
+     <item name="x" type="UINT8U"/>
+   </struct>
+   <struct name="D">
+     <item name="x" type="UINT8U"/>
+     <item name="c" type="C"/>
+   </struct>
 </configurator>