What this plugin is
Data Modelling is a reusable, plugin-based data-model browser. It blends the platform's own data-model views with a minimalistic Plugin › Type navigation so you can walk the data model of any installed plugin without writing a page for it.
It ships one NodeType — DataModelling/DataModelExplorer — and one instance of it,
DataModelling/Explorer, which is the browser.
The areas
| Area | What it shows | How it's built |
|---|---|---|
Overview |
The curated index: a search over every type, the Featured models (modules that declare dataModelIndex.featured) as cards with their description, type count and main types as chips, then every other module as a compact tile grouped by its declared domain, with the platform's own types and the dependency table in their own tabs. |
Controls.MeshSearch (nodeType:NodeType), Controls.LayoutGrid of Stack cards, Controls.FieldStrip, Controls.ChipBar, Controls.Tabs. The modules and their declarations are read live off each root's content. |
Plugin |
One plugin: a breadcrumb, Depends on / Required by as chips, the plugin's UML class diagram, and its types as tiles. | The diagram is the platform's Controls.UmlClassDiagram. Its classes are the plugin's types whose content schema has data; view-only types such as galleries and app pages have none and are left out. Its associations are the x-meshNode references those schemas carry, and a referenced type of another plugin is drawn as a dashed foreign class that links to its page. Above 14 classes the diagram centres on the declared types and their neighbours; …/Plugin/{root}?all draws everything. |
Type |
One type: a breadcrumb, its name, the plugin as a chip (its label bound to the plugin root's own name), then UML (the type plus its direct neighbours), Properties (the content type's property table), JSON Schema and Members. | UML is this plugin's Uml area over the same projection. Properties and JSON Schema embed the type node's own $Model/{name} and $Schema, which describe its content type. |
Open a plugin at /DataModelling/Explorer/Plugin/{root} (e.g.
…/Plugin/Reinsurance), or a type at
/DataModelling/Explorer/Type/{typePath} with the path percent-encoded, so / becomes %2F
(e.g. …/Type/Reinsurance%2FAcceptance).
Older ~ links still open.
Declaring a dependency
A plugin declares the partition roots it builds on with a dependsOn string array on its
index.json PluginContent, e.g. "dependsOn": ["Reinsurance", "LossModelling"] on Pricing.
The array rides in PluginContent's round-trip buffer, so no compiled type changes. The browser
reads it live and shows both directions as chips: Depends on and Required by.
Joining the front index: dataModelIndex
A module declares whether it leads the index. Nothing is derived from what it happens to contain
(policy declared-not-derived), and a module that declares nothing is not featured. The
declaration is an object on its root's index.json content:
"dataModelIndex": {
"featured": true,
"domain": "Insurance",
"order": 10,
"types": ["Acceptance", "Claim", "Submission"]
}
| Field | Meaning |
|---|---|
featured |
JSON true puts the module in the Featured models band; anything else does not. |
domain |
The group the module is listed under: free text such as Insurance, Platform or Daily work. A module without one is listed under Other. |
order |
Sort key within the band or group; lower comes first. Without it, modules sort by name after the ordered ones. |
types |
The module's main types, as leaf names or full paths. They are its card's chips, they are starred on its page, and they are the centre of its diagram when the model is large. |
Every field is read shape-tolerantly: a missing or malformed value means "not declared", never an error.
House rules this plugin follows
- 100% reactive — no
async/await. Every area returnsIObservable<UiControl?>; the one mesh query goes throughControls.MeshSearch. - Framework controls + data binding — no hand-rolled HTML.
Controls.Stack/Markdown/Tabs/LayoutArea/MeshSearch. Navigation is markdown links, not<a>blobs. - DRY. All URL/query logic lives once in
DataModelExplorerLogic; the areas never re-implement it. - Tested.
DataModelExplorerTestscovers every logic method; theTestslayout area runs them and renders a pass/fail table (asserted green in CI).
See the /plugin skill for how to build a plugin like this from scratch.
The modelling skills
Beside the browser, this plugin ships four Skill nodes that teach how to model data on
MeshWeaver — procedures an agent can follow, every claim grounded in the framework source
(MeshWeaver.Domain) and the worked domains (Reinsurance/, UWDeepfield/Source):
| Skill | What it covers |
|---|---|
| /discover-cube | Recognizing a dimensional scenario and proposing facts / measures / dimensions from a domain description — grain statement, field classification, anti-signals. |
| /model-cube | Modelling dimensions and fact records with the right attributes — node-per-member vs CLR-typed members, the [Dimension]/[IdentityProperty]/[NotVisible] coordinate triple, money and sign-convention guards. |
| /model-foreign-keys | FK relationships — [MeshNode("query")] node-path pickers, [MeshNodeCollection], self-referential hierarchies, [MeshNodeProperty] sync, and what draws a UML edge. |
| /domain-attributes | The reference tour of every data-modelling attribute in MeshWeaver.Domain, one line + real example each. |
They cross-link the free Data Modeling Masterclass course, whose lessons 16–18 drill the same ground hands-on.
The Members view renders before the query answers
The Members view follows the platform rule "Templates first, data later" (core Doc/GUI/DataBinding). Its table is a markdown block bound to MembersViewModel, which starts on the loading line. The framework's paged list is the template's one slot: it runs a live query of its own, so it is mounted only on overflow, never kept in the page behind a hidden style. DataModelExplorerTemplateTests asserts both.
The Type page is a template too: it reads nothing on the hub. The plugin chip's label is a pointer into the plugin root node's name, resolved by the GUI through the node stream, so the header renders at once and a renamed root reaches an open page. The breadcrumb takes plain text, so it shows the root's path, spaced into words.