diff --git a/mitm_tooling/io/importing.py b/mitm_tooling/io/importing.py
index 8591c2e28eb3e1512f3958aafaab15dd24a144d2..113b67b3ee6e338b1cad8f36078f493871198694 100644
--- a/mitm_tooling/io/importing.py
+++ b/mitm_tooling/io/importing.py
@@ -1,9 +1,11 @@
 import glob
 import logging
 import os.path
-import pydantic
 import zipfile
 from abc import ABC, abstractmethod
+
+import pydantic
+
 from mitm_tooling.definition import MITM, get_mitm_def
 from mitm_tooling.representation.file_representation import read_header_file, read_data_file
 from mitm_tooling.representation.intermediate_representation import MITMData, Header
@@ -23,7 +25,7 @@ class FileImport(pydantic.BaseModel, ABC):
 
 class ZippedImport(FileImport):
 
-    def read(self, source: DataSource, **kwargs) -> MITMData | None:
+    def read(self, source: DataSource, header_only: bool = False, **kwargs) -> MITMData | None:
         mitm_def = get_mitm_def(self.mitm)
         with use_bytes_io(source, expected_file_ext='.zip', mode='rb') as f:
             parts = {}
@@ -31,19 +33,20 @@ class ZippedImport(FileImport):
                 with zf.open('header.csv') as h:
                     parts['header'] = read_header_file(h, normalize=True)
                 files_in_zip = set(zf.namelist())
-                for concept in mitm_def.main_concepts:
-                    fn = ensure_ext(mitm_def.get_properties(concept).plural, '.csv')
-                    if fn in files_in_zip:
-                        with zf.open(fn) as cf:
-                            parts[concept] = read_data_file(cf, target_mitm=self.mitm, target_concept=concept,
-                                                            normalize=True)
+                if not header_only:
+                    for concept in mitm_def.main_concepts:
+                        fn = ensure_ext(mitm_def.get_properties(concept).plural, '.csv')
+                        if fn in files_in_zip:
+                            with zf.open(fn) as cf:
+                                parts[concept] = read_data_file(cf, target_mitm=self.mitm, target_concept=concept,
+                                                                normalize=True)
             assert 'header' in parts
             return MITMData(header=Header.from_df(parts.pop('header'), self.mitm), concept_dfs=parts)
 
 
 class FolderImport(FileImport):
 
-    def read(self, source: DataSource, **kwargs) -> MITMData | None:
+    def read(self, source: DataSource, header_only: bool = False, **kwargs) -> MITMData | None:
         assert isinstance(source, FilePath)
         assert os.path.exists(source)
 
@@ -55,15 +58,16 @@ class FolderImport(FileImport):
         with use_for_pandas_io('header.csv') as f:
             parts['header'] = read_header_file(f, normalize=True)
 
-        for concept in mitm_def.main_concepts:
-            fn = ensure_ext(mitm_def.get_properties(concept).plural, '.csv')
-            if fn in file_names:
-                parts[concept] = read_data_file(fn, target_mitm=self.mitm, target_concept=concept, normalize=True)
+        if not header_only:
+            for concept in mitm_def.main_concepts:
+                fn = ensure_ext(mitm_def.get_properties(concept).plural, '.csv')
+                if fn in file_names:
+                    parts[concept] = read_data_file(fn, target_mitm=self.mitm, target_concept=concept, normalize=True)
 
         return MITMData(header=Header.from_df(parts.pop('header'), self.mitm), concept_dfs=parts)
 
 
-def read_zip(source: DataSource, mitm: MITM | None = None) -> MITMData | None:
+def read_zip(source: DataSource, mitm: MITM | None = None, header_only: bool = False, **kwargs) -> MITMData | None:
     filename = None
     if isinstance(source, FilePath):
         filename = source
@@ -74,6 +78,6 @@ def read_zip(source: DataSource, mitm: MITM | None = None) -> MITMData | None:
             except ValueError:
                 pass
     if mitm:
-        return ZippedImport(mitm=mitm, filename=filename).read(source)
+        return ZippedImport(mitm=mitm, filename=filename).read(source, header_only=header_only, **kwargs)
     else:
         logger.error('Attempted to import data with unspecified MitM.')
diff --git a/mitm_tooling/transformation/superset/common.py b/mitm_tooling/transformation/superset/common.py
index 2f14c49e36d4ad98c9b0ede6961e5ff6743e57b9..1d5f717d8c8a0b83d9a152884a4687b0cf7022c6 100644
--- a/mitm_tooling/transformation/superset/common.py
+++ b/mitm_tooling/transformation/superset/common.py
@@ -1,12 +1,14 @@
+from uuid import UUID
+
 import pydantic
 import sqlalchemy as sa
 from mitm_tooling.representation.sql.common import SchemaName
 from mitm_tooling.representation.sql_representation import SQL_REPRESENTATION_DEFAULT_SCHEMA
-from mitm_tooling.transformation.superset.definitions import StrUrl
+from .definitions import StrUrl
+from .factories.utils import mk_short_uuid_str
 from mitm_tooling.utilities.io_utils import FilePath
 from mitm_tooling.utilities.sql_utils import create_sa_engine, dialect_cls_from_url, any_url_into_sa_url
 from pydantic import AnyUrl, ConfigDict
-from pydantic.v1 import UUID4
 from typing import Type
 
 SQLiteFileOrEngine = FilePath | sa.Engine
@@ -33,8 +35,8 @@ class SupersetDBConnectionInfo(pydantic.BaseModel):
         return dialect_cls_from_url(self.sql_alchemy_uri)
 
 
-def name_plus_uuid(name: str, uuid: UUID4) -> str:
-    return f'{name}-{uuid.hex[:8]}'
+def name_plus_uuid(name: str, uuid: UUID | None = None) -> str:
+    return f'{name}-{mk_short_uuid_str(uuid)}'
 
 
 def _mk_engine(arg: SQLiteFileOrEngine) -> sa.Engine:
diff --git a/mitm_tooling/transformation/superset/definitions/assets.py b/mitm_tooling/transformation/superset/definitions/assets.py
index f04b7c2f8e424ce1927de9e506c122655b1c6cbb..b9afac1fd925c2f8fae571e421c957eff4ef110c 100644
--- a/mitm_tooling/transformation/superset/definitions/assets.py
+++ b/mitm_tooling/transformation/superset/definitions/assets.py
@@ -4,6 +4,7 @@ from datetime import UTC
 
 from mitm_tooling.definition import MITM
 from .charts import *
+from .dashboard import DashboardPositionData, DashboardMetadata
 from .post_processing import *
 
 
@@ -103,9 +104,10 @@ class SupersetChartDef(SupersetDefFile):
     description: str | None = None
     certified_by: str | None = None
     certification_details: str | None = None
-    params: ChartParams | dict[str, Any] = pydantic.Field(default_factory=dict)
+    params: ChartParams | None = None
     query_context: Annotated[pydantic.Json | QueryContext | None, pydantic.PlainSerializer(
-        lambda x: x.model_dump_json(by_alias=True, exclude_none=True) if isinstance(x, pydantic.BaseModel) else x,
+        lambda x: x.model_dump_json(by_alias=True, exclude_none=True, serialize_as_any=True) if isinstance(x,
+                                                                                                           pydantic.BaseModel) else x,
         return_type=pydantic.Json), pydantic.Field(default=None)]
     cache_timeout: int | None = None
     version: str = '1.0.0'
@@ -120,11 +122,11 @@ class SupersetChartDef(SupersetDefFile):
 class SupersetDashboardDef(SupersetDefFile):
     uuid: StrUUID
     dashboard_title: str
+    position: DashboardPositionData
+    metadata: DashboardMetadata
     description: str | None = None
     css: str | None = None
     slug: str | None = None
-    position: dict[str, Any] = pydantic.Field(default_factory=dict)
-    metadata: dict[str, Any] = pydantic.Field(default_factory=dict)
     is_managed_externally: bool | None = False
     external_url: StrUrl | None = None
     certified_by: str | None = None
@@ -170,6 +172,8 @@ class SupersetAssetsDef(SupersetDefFolder):
             folder_dict['datasets'] = db_dss
         if self.charts:
             folder_dict['charts'] = self.charts
+        if self.dashboards:
+            folder_dict['dashboards'] = self.dashboards
         return {'my_import': folder_dict}
 
 
diff --git a/mitm_tooling/transformation/superset/definitions/core.py b/mitm_tooling/transformation/superset/definitions/core.py
index 527acbdb81ef8e9a3242797ded7b47adaa171b67..e2bee4b68b5f9cd919d400e3443bf2f90de80892 100644
--- a/mitm_tooling/transformation/superset/definitions/core.py
+++ b/mitm_tooling/transformation/superset/definitions/core.py
@@ -179,7 +179,7 @@ class QueryContext(BaseSupersetDefinition):
 
     datasource: DatasourceIdentifier
     queries: list[QueryObject] = pydantic.Field(default_factory=list)
-    form_data: FormData | dict[str, Any] | None = pydantic.Field(default=None)
+    form_data: FormData | None = pydantic.Field(default=None)
     result_type: ChartDataResultType = ChartDataResultType.FULL
     result_format: ChartDataResultFormat = ChartDataResultFormat.JSON
     force: bool = False
diff --git a/mitm_tooling/transformation/superset/definitions/dashboard.py b/mitm_tooling/transformation/superset/definitions/dashboard.py
index 4c30dffb0e395c4a25e6190d755c5346b069ac48..a2263ed2caf00b93050e462e0cb188747d21c745 100644
--- a/mitm_tooling/transformation/superset/definitions/dashboard.py
+++ b/mitm_tooling/transformation/superset/definitions/dashboard.py
@@ -1,12 +1,9 @@
 from enum import StrEnum
 from typing import Literal
-from uuid import UUID
 
 import pydantic
 
-from mitm_tooling.representation import ColumnName
 from .constants import StrUUID
-from ..factories.utils import mk_uuid
 
 DashboardInternalID = str
 
@@ -39,18 +36,28 @@ class DashboardHeader(DashboardComponent):
     meta: HeaderMeta
 
 
+class DashboardRoot(DashboardComponent):
+    type: Literal[DashboardComponentType.ROOT] = DashboardComponentType.ROOT
+    meta: None = None
+
+
+class DashboardGrid(DashboardComponent):
+    type: Literal[DashboardComponentType.GRID] = DashboardComponentType.GRID
+    meta: None = None
+
+
 class RowMeta(ComponentMeta):
     background: str = 'BACKGROUND_TRANSPARENT'
 
 
 class DashboardRow(DashboardComponent):
     type: Literal[DashboardComponentType.ROW] = DashboardComponentType.ROW
-    meta: RowMeta
+    meta: RowMeta = RowMeta()
 
 
 class ChartMeta(ComponentMeta):
     uuid: StrUUID
-    width: int
+    width: int = pydantic.Field(ge=1, le=12)
     height: int
     chartId: int | None = None
     sliceName: str | None = None
@@ -66,15 +73,6 @@ DASHBOARD_VERSION_KEY_LITERAL = Literal['DASHBOARD_VERSION_KEY']
 DashboardPositionData = dict[DASHBOARD_VERSION_KEY_LITERAL | DashboardInternalID, str | DashboardComponent]
 
 
-def mk_dashboard_position_data(chart_grid: list[list[DashboardChart]]) -> DashboardPositionData:
-    res = {
-        'DASHBOARD_VERSION_KEY': 'v2',
-        'HEADER_ID': ...
-    }
-
-    return res
-
-
 class ControlValues(pydantic.BaseModel):
     enableEmptyFilter: bool = False
     defaultToFirstItem: bool | None = False
@@ -109,19 +107,6 @@ class NativeFilterConfig(pydantic.BaseModel):
     type: str = 'NATIVE_FILTER'
 
 
-def mk_filter_config(name: str, target_cols: list[tuple[ColumnName, UUID]], ft: FilterType = FilterType.FILTER_SELECT,
-                     control_values: ControlValues = ControlValues()) -> NativeFilterConfig:
-    return NativeFilterConfig(
-        id=f'NATIVE_FILTER-{mk_uuid().hex[:12]}',
-        name=name,
-        filterType=ft,
-        controlValues=control_values,
-        targets=[
-            ColumnOfDataset(column=ColName(name=c), datasetUuid=ds_uuid) for c, ds_uuid in (target_cols or [])
-        ]
-    )
-
-
 class DashboardMetadata(pydantic.BaseModel):
     color_scheme: str = 'blueToGreen'
     cross_filters_enabled: bool = True
diff --git a/mitm_tooling/transformation/superset/exporting.py b/mitm_tooling/transformation/superset/exporting.py
index 87c20421ddc1e14d4af978b4eec96a3db66722c3..52dca2901982890ee8f18c31eb560830775acbbc 100644
--- a/mitm_tooling/transformation/superset/exporting.py
+++ b/mitm_tooling/transformation/superset/exporting.py
@@ -16,7 +16,7 @@ def write_superset_def_as_zip(target: ByteSink, superset_def: SupersetDefFolder)
                     fn = f'{arg.filename}.yaml'
                     if prefix:
                         fn = os.path.join(prefix, fn)
-                    dump = arg.model_dump(by_alias=True, mode='python', exclude_none=True)
+                    dump = arg.model_dump(by_alias=True, mode='python', exclude_none=True, serialize_as_any=True)
                     s = yaml.dump(dump, default_flow_style=False)
 
                     zf.writestr(fn, s)
diff --git a/mitm_tooling/transformation/superset/factories/charts.py b/mitm_tooling/transformation/superset/factories/charts.py
index 4bbd85f0c698ff6a0b40e3dfe2d6f6482124e52c..cb7939551c409591735155aca2685369e88d27a9 100644
--- a/mitm_tooling/transformation/superset/factories/charts.py
+++ b/mitm_tooling/transformation/superset/factories/charts.py
@@ -1,5 +1,4 @@
-from pydantic import UUID4
-
+from uuid import UUID
 from mitm_tooling.data_types import MITMDataType
 from mitm_tooling.utilities.python_utils import unique
 from .core import mk_empty_adhoc_time_filter, mk_adhoc_metric, mk_pivot_post_processing, mk_adhoc_column
@@ -13,7 +12,7 @@ from mitm_tooling.representation import ColumnName
 
 
 def mk_pie_chart(name: str, datasource_identifier: DatasourceIdentifier, col: ColumnName, dt: MITMDataType,
-                 groupby_cols: list[ColumnName] | None = None, uuid: UUID4 | None = None) -> SupersetChartDef:
+                 groupby_cols: list[ColumnName] | None = None, uuid: UUID | None = None) -> SupersetChartDef:
     groupby_cols = groupby_cols or []
     metric = mk_adhoc_metric(col, agg=SupersetAggregate.COUNT, dt=dt)
     params = PieChartParams(datasource=datasource_identifier,
@@ -40,7 +39,7 @@ def mk_time_series_bar_chart(name: str,
                              x_col: ColumnName,
                              groupby_cols: list[ColumnName] | None = None,
                              filters: list[SupersetAdhocFilter] | None = None,
-                             uuid: UUID4 | None = None,
+                             uuid: UUID | None = None,
                              time_grain: TimeGrain | None = None) -> SupersetChartDef:
     groupby_cols = groupby_cols or []
     metric = mk_adhoc_metric(y_col, agg=SupersetAggregate.COUNT, dt=y_dt)
@@ -78,7 +77,7 @@ def mk_avg_count_time_series_chart(name: str,
                                    groupby_cols: list[ColumnName],
                                    time_col: ColumnName = 'time',
                                    filters: list[SupersetAdhocFilter] | None = None,
-                                   uuid: UUID4 | None = None,
+                                   uuid: UUID | None = None,
                                    time_grain: TimeGrain | None = None):
     groupby_cols = groupby_cols or []
     metric = mk_adhoc_metric(time_col, agg=SupersetAggregate.COUNT, dt=MITMDataType.Datetime)
diff --git a/mitm_tooling/transformation/superset/factories/dashboard.py b/mitm_tooling/transformation/superset/factories/dashboard.py
index b66224cce692beadf12fffa41e03f4bece1d92d7..f72fe18e53847399d3d55ae59139c6e34589528e 100644
--- a/mitm_tooling/transformation/superset/factories/dashboard.py
+++ b/mitm_tooling/transformation/superset/factories/dashboard.py
@@ -1,14 +1,76 @@
 from typing import Any
+from uuid import UUID
 
-from pydantic import UUID4
+from mitm_tooling.representation import ColumnName
+from mitm_tooling.transformation.superset.definitions import SupersetDashboardDef, SupersetChartDef
+from mitm_tooling.transformation.superset.factories.utils import mk_uuid, mk_short_uuid_str
+from ..definitions.dashboard import *
 
-from mitm_tooling.transformation.superset.definitions import SupersetDashboardDef
-from mitm_tooling.transformation.superset.factories.utils import mk_uuid
 
+def mk_filter_config(name: str, target_cols: list[tuple[ColumnName, UUID]], ft: FilterType = FilterType.FILTER_SELECT,
+                     control_values: ControlValues = ControlValues()) -> NativeFilterConfig:
+    return NativeFilterConfig(
+        id=f'NATIVE_FILTER-{mk_short_uuid_str()}',
+        name=name,
+        filterType=ft,
+        controlValues=control_values,
+        targets=[
+            ColumnOfDataset(column=ColName(name=c), datasetUuid=ds_uuid) for c, ds_uuid in (target_cols or [])
+        ]
+    )
 
-def mk_superset_dashboard(title: str,
-                          position: dict[str, Any],
-                          description: str | None = None,
-                          uuid: UUID4 | None = None) -> SupersetDashboardDef:
-    return SupersetDashboardDef(dashboard_title=title, position=position, description=description,
-                                uuid=uuid or mk_uuid())
+
+def mk_dashboard_base(header_text: str, row_ids: list[DashboardInternalID]) -> DashboardPositionData:
+    return {
+        'DASHBOARD_VERSION_KEY': 'v2',
+        'HEADER_ID': DashboardHeader(id='HEADER_ID', meta=HeaderMeta(text=header_text)),
+        'ROOT_ID': DashboardRoot(id='ROOT_ID', children=['GRID_ID']),
+        'GRID_ID': DashboardGrid(id='GRID_ID', children=row_ids),
+    }
+
+
+def mk_dashboard_row(children_ids: list[DashboardInternalID], id: DashboardInternalID | None = None) -> DashboardRow:
+    return DashboardRow(id=id or f'ROW-{mk_short_uuid_str()}', children=children_ids)
+
+
+def mk_dashboard_chart(chart_uuid: UUID, width: int, height: int, slice_name: str | None = None,
+                       id: DashboardInternalID | None = None) -> DashboardChart:
+    return DashboardChart(id=id or f'CHART-{mk_short_uuid_str()}',
+                          meta=ChartMeta(uuid=chart_uuid, width=width, height=height, sliceName=slice_name))
+
+def chart_def_into_dashboard_chart(chart_def: SupersetChartDef, width: int, height: int) -> DashboardChart:
+    return mk_dashboard_chart(chart_uuid=chart_def.uuid, width=width, height=height)
+
+def mk_dashboard_position_data(header_text: str, chart_grid: list[list[DashboardChart]]) -> DashboardPositionData:
+    row_ids = []
+    elements = {}
+    for row in chart_grid:
+        within_row_ids = []
+        for chart in row:
+            # mk_dashboard_chart()
+            elements[chart.id] = chart
+            within_row_ids.append(chart.id)
+        row = mk_dashboard_row(within_row_ids)
+        elements[row.id] = row
+        row_ids.append(row.id)
+    position_base = mk_dashboard_base(header_text=header_text, row_ids=row_ids)
+
+    res = position_base | elements
+    return res
+
+
+def mk_dashboard_metadata(native_filters: list[NativeFilterConfig]) -> DashboardMetadata:
+    return DashboardMetadata(native_filter_configuration=native_filters)
+
+
+def mk_dashboard_def(dashboard_title, chart_grid: list[list[DashboardChart]], native_filters: list[NativeFilterConfig],
+                     description: str | None = None, uuid: UUID | None = None) -> SupersetDashboardDef:
+    position_data = mk_dashboard_position_data(dashboard_title, chart_grid)
+    dashboard_metadata = mk_dashboard_metadata(native_filters=native_filters)
+    return SupersetDashboardDef(
+        dashboard_title=dashboard_title,
+        position=position_data,
+        metadata=dashboard_metadata,
+        description=description,
+        uuid=uuid or mk_uuid(),
+    )
diff --git a/mitm_tooling/transformation/superset/factories/database.py b/mitm_tooling/transformation/superset/factories/database.py
index d853bc67d97d2121fa77653383b0327f34bfb3e0..f4befd77ef4e8245f62ecb6429f3a79ce99f11df 100644
--- a/mitm_tooling/transformation/superset/factories/database.py
+++ b/mitm_tooling/transformation/superset/factories/database.py
@@ -1,4 +1,6 @@
-from pydantic import AnyUrl, UUID4
+from uuid import UUID
+
+from pydantic import AnyUrl
 
 from .utils import mk_uuid
 from ..common import name_plus_uuid
@@ -7,7 +9,7 @@ from ..definitions import SupersetDatabaseDef
 
 def mk_database(name: str,
                 sqlalchemy_uri: AnyUrl,
-                uuid: UUID4 | None = None,
+                uuid: UUID | None = None,
                 uniquify_name: bool = False) -> SupersetDatabaseDef:
     uuid = uuid or mk_uuid()
     if uniquify_name:
diff --git a/mitm_tooling/transformation/superset/factories/dataset.py b/mitm_tooling/transformation/superset/factories/dataset.py
index f21c661bb8f25b6cc4ecfcb4967df5933959938b..6f172977159061e233a0e38b5625dd6fdc1b2e4d 100644
--- a/mitm_tooling/transformation/superset/factories/dataset.py
+++ b/mitm_tooling/transformation/superset/factories/dataset.py
@@ -1,3 +1,5 @@
+from uuid import UUID
+
 import pydantic
 import sqlalchemy as sa
 
@@ -9,8 +11,8 @@ from .utils import mk_uuid
 from ..definitions import SupersetAggregate
 
 
-def mk_dataset(tm: TableMetaInfo, database_uuid: pydantic.UUID4, dialect: sa.Dialect | None = None,
-               uuid: pydantic.UUID4 | None = None) -> SupersetDatasetDef:
+def mk_dataset(tm: TableMetaInfo, database_uuid: UUID, dialect: sa.Dialect | None = None,
+               uuid: UUID | None = None) -> SupersetDatasetDef:
     cols = []
     metrics = [mk_metric('*', SupersetAggregate.COUNT)]
     for c in tm.columns:
diff --git a/mitm_tooling/transformation/superset/factories/mitm_dataset.py b/mitm_tooling/transformation/superset/factories/mitm_dataset.py
index 21802d49133f0aab62d024bcdc314b067914a852..a55f4b7e36512c59bb1bbb6352aa1f12b7001e94 100644
--- a/mitm_tooling/transformation/superset/factories/mitm_dataset.py
+++ b/mitm_tooling/transformation/superset/factories/mitm_dataset.py
@@ -1,11 +1,15 @@
-from pydantic.v1 import UUID4
+from uuid import UUID
 
 from mitm_tooling.definition import MITM
-from mitm_tooling.transformation.superset.definitions import SupersetMitMDatasetDef
-from mitm_tooling.transformation.superset.factories.utils import mk_uuid
+from ..common import name_plus_uuid
+from ..definitions import SupersetMitMDatasetDef
+from ..factories.utils import mk_uuid
 
 
-def mk_mitm_dataset(name: str, mitm: MITM, database_uuid: UUID4, uuid: UUID4 | None = None) -> SupersetMitMDatasetDef:
+def mk_mitm_dataset(name: str, mitm: MITM, database_uuid: UUID, uuid: UUID | None = None, uniquify_name: bool = False) -> SupersetMitMDatasetDef:
+    uuid = uuid or mk_uuid()
+    if uniquify_name:
+        name = name_plus_uuid(name, uuid)
     return SupersetMitMDatasetDef(
         dataset_name=name,
         mitm=mitm,
diff --git a/mitm_tooling/transformation/superset/factories/mitm_specific/maed_charts.py b/mitm_tooling/transformation/superset/factories/mitm_specific/maed_charts.py
index b317319afdc2e13e4295e639aecc136b06efa482..c1f37ca897f9802764197b25f83d2925cdea63ab 100644
--- a/mitm_tooling/transformation/superset/factories/mitm_specific/maed_charts.py
+++ b/mitm_tooling/transformation/superset/factories/mitm_specific/maed_charts.py
@@ -8,8 +8,8 @@ from ...definitions import SupersetChartDef, FilterOperator
 
 
 def mk_maed_charts(header: Header, superset_datasource_bundle: SupersetDatasourceBundle,
-                   sql_rep_schema: SQLRepresentationSchema | None = None) -> list[
-    SupersetChartDef]:
+                   sql_rep_schema: SQLRepresentationSchema | None = None) -> dict[str,
+SupersetChartDef]:
     sql_rep_schema = sql_rep_schema or mk_sql_rep_schema(header)
     ds_ids = superset_datasource_bundle.placeholder_dataset_identifiers
 
@@ -37,4 +37,5 @@ def mk_maed_charts(header: Header, superset_datasource_bundle: SupersetDatasourc
 
     ts = mk_avg_count_time_series_chart(f'{type_name} Time Series', ds_ids[tbl.name], groupby_cols=['object'],
                                         filters=[mk_adhoc_filter('kind', FilterOperator.EQUALS, 'M')])
-    return [event_counts_ts, measurement_counts_ts, objects_pie, ts]
+    return {'event-count-ts': event_counts_ts, 'measurement-count-ts': measurement_counts_ts,
+            'objects-pie': objects_pie, 'ts': ts}
diff --git a/mitm_tooling/transformation/superset/factories/mitm_specific/maed_dashboards.py b/mitm_tooling/transformation/superset/factories/mitm_specific/maed_dashboards.py
index 217a184d3875a5352bdc55dc383c838ae3fb15bf..94233a54200509c85a6a2f928bf45424b002801b 100644
--- a/mitm_tooling/transformation/superset/factories/mitm_specific/maed_dashboards.py
+++ b/mitm_tooling/transformation/superset/factories/mitm_specific/maed_dashboards.py
@@ -1,11 +1,15 @@
 from mitm_tooling.representation import Header
 from mitm_tooling.transformation.superset.definition_bundles import SupersetDatasourceBundle
-from mitm_tooling.transformation.superset.definitions import SupersetDashboardDef
-from mitm_tooling.transformation.superset.factories.dashboard import mk_superset_dashboard
+from mitm_tooling.transformation.superset.definitions import SupersetDashboardDef, SupersetChartDef
+from mitm_tooling.transformation.superset.factories.dashboard import mk_dashboard_def, mk_dashboard_chart
 from mitm_tooling.transformation.superset.factories.mitm_specific.maed_charts import mk_maed_charts
 
 
-def mk_maed_dashboard(header: Header, datasource_bundle: SupersetDatasourceBundle) -> SupersetDashboardDef:
+def mk_maed_dashboard(header: Header, datasource_bundle: SupersetDatasourceBundle) -> tuple[SupersetDashboardDef, list[SupersetChartDef]]:
     charts = mk_maed_charts(header, datasource_bundle)
-    position = {}
-    return mk_superset_dashboard('MAED Dashboard', position, description='A rudimentary dashboard to view MAED data.')
+    chart_grid = [[mk_dashboard_chart(chart_uuid=charts['objects-pie'].uuid, width=4, height=50),
+                   mk_dashboard_chart(chart_uuid=charts['event-count-ts'].uuid, width=4, height=50),
+                   mk_dashboard_chart(chart_uuid=charts['measurement-count-ts'].uuid, width=4, height=50)],
+                  [mk_dashboard_chart(chart_uuid=charts['ts'].uuid, width=12, height=100)]]
+    return mk_dashboard_def('MAED Dashboard', chart_grid=chart_grid, native_filters=[],
+                            description='A rudimentary dashboard to view MAED data.'), list(charts.values())
diff --git a/mitm_tooling/transformation/superset/factories/utils.py b/mitm_tooling/transformation/superset/factories/utils.py
index d98c6f0eb4b3a62b0351911a1d4eef85ebf64558..86ebcab95db6f3227a0688c542f03a68c7543287 100644
--- a/mitm_tooling/transformation/superset/factories/utils.py
+++ b/mitm_tooling/transformation/superset/factories/utils.py
@@ -5,3 +5,7 @@ import pydantic
 
 def mk_uuid() -> pydantic.UUID4:
     return uuid.uuid4()
+
+
+def mk_short_uuid_str(existing_uuid: uuid.UUID | None = None) -> str:
+    return (existing_uuid or mk_uuid()).hex[:12]
diff --git a/mitm_tooling/transformation/superset/mitm_specific/maed_visualization.py b/mitm_tooling/transformation/superset/mitm_specific/maed_visualization.py
index 4594f62eb80b0bc56313283b900c36b13088fd27..ff48e1a184a4e0487453c73c5854cfa4b86e8f60 100644
--- a/mitm_tooling/transformation/superset/mitm_specific/maed_visualization.py
+++ b/mitm_tooling/transformation/superset/mitm_specific/maed_visualization.py
@@ -9,6 +9,5 @@ def mk_maed_visualization(header: Header,
                           superset_datasource_bundle: SupersetDatasourceBundle) -> SupersetVisualizationBundle:
     ds_ids = superset_datasource_bundle.placeholder_dataset_identifiers
 
-    charts = mk_maed_charts(header, superset_datasource_bundle)
-    dashboard = mk_maed_dashboard(header, superset_datasource_bundle)
+    dashboard, charts = mk_maed_dashboard(header, superset_datasource_bundle)
     return SupersetVisualizationBundle(charts=charts, dashboards=[dashboard])
diff --git a/test/something.py b/test/something.py
index a8eb9c89144cd5a988231b2600cabafa051d224e..8a9850e7a347ce196dcaa0955ccf5bde25166e01 100644
--- a/test/something.py
+++ b/test/something.py
@@ -1,13 +1,14 @@
 import os
 import unittest
 
-from mitm_tooling.transformation.superset.factories.utils import mk_uuid
+from pydantic import AnyUrl
+
+from mitm_tooling.transformation.superset.common import name_plus_uuid
 
 
 class MyTestCase(unittest.TestCase):
     def test_something(self):
-        import mitm_tooling
-        from mitm_tooling.io.exporting import get_mitm_def
+        pass
 
     def test_sql_repr(self):
         from mitm_tooling.representation import Header, HeaderEntry, mk_sql_rep_schema
@@ -29,7 +30,7 @@ class MyTestCase(unittest.TestCase):
         print()
 
     def test_writing_sqlite(self):
-        from mitm_tooling.representation import Header, HeaderEntry, mk_sql_rep_schema, MITMData, mk_sqlite
+        from mitm_tooling.representation import Header, HeaderEntry, MITMData, mk_sqlite
         from mitm_tooling.definition import MITM
         from mitm_tooling.data_types import MITMDataType
         h = Header(mitm=MITM.MAED, header_entries=[
@@ -60,20 +61,30 @@ class MyTestCase(unittest.TestCase):
             os.remove('synthetic-variation.sqlite')
         mk_sqlite(syn, 'synthetic-variation.sqlite')
 
-    def test_superset(self):
-        from mitm_tooling.transformation.superset import write_inferred_superset_dataset_import
-        write_inferred_superset_dataset_import('superset_import', 'synthetic.sqlite')
-
-    def test_superset_variation(self):
-        from mitm_tooling.transformation.superset import write_inferred_superset_dataset_import
-        write_inferred_superset_dataset_import('superset_import_variation', 'synthetic-variation.sqlite')
+    def test_superset_dataset_assets(self):
+        from mitm_tooling.io import importing, MITM
+        syn = importing.read_zip('synthetic.maed', MITM.MAED, header_only=True)
+        from mitm_tooling.transformation.superset import mk_superset_mitm_dataset_import, write_superset_assets_def
+        dataset_import = mk_superset_mitm_dataset_import(syn.header,
+                                                         sql_alchemy_uri=AnyUrl('sqlite://synthetic-variation.sqlite'),
+                                                         dataset_name=name_plus_uuid('SyntheticExampleDataset'),
+                                                         explicit_db_name='SyntheticExampleDB',
+                                                         schema_name='main')
+        write_superset_assets_def('superset_dataset_import', dataset_import.to_assets())
 
-    def test_superset_assets(self):
-        from mitm_tooling.transformation.superset import (write_superset_dashboard_import, mk_superset_dataset_import)
+    def test_superset_viz_assets(self):
         from mitm_tooling.io import importing, MITM
-        syn = importing.read_zip('synthetic.maed', MITM.MAED)
-        write_superset_dashboard_import(syn, output_path='superset_dashboard_import',
-                                        db_name=f'synthetic-{mk_uuid().hex[:4]}')
+        syn = importing.read_zip('synthetic.maed', MITM.MAED, header_only=True)
+        from mitm_tooling.transformation.superset import mk_superset_mitm_dataset_import, write_superset_assets_def
+        dataset_import = mk_superset_mitm_dataset_import(syn.header,
+                                                         sql_alchemy_uri=AnyUrl('sqlite://synthetic-variation.sqlite'),
+                                                         dataset_name=name_plus_uuid('SyntheticExampleDataset'),
+                                                         explicit_db_name='SyntheticExampleDB',
+                                                         schema_name='main')
+
+        from mitm_tooling.transformation.superset import mk_superset_visualization_import
+        visualization_import = mk_superset_visualization_import(syn.header, dataset_import.datasource_bundle)
+        write_superset_assets_def('superset_viz_import', visualization_import.to_assets())
 
 
 if __name__ == '__main__':