From b971c9d5f574ad16457b9fdf3bb7c89aa5a2eae0 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 24 Jul 2026 12:43:53 +0000 Subject: [PATCH] docs(proposals): add Atlas Design System skill proposal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Land the atlas-design proposal — a taste + workflow skill layer that makes mxcli-generated Mendix apps look designed by default (the Atlas-first method, 4-layer token architecture, recipe library, chart/dark-mode widget recipes, a gotchas catalog, and a mandatory runtime-verify loop). It sits on top of the page-styling, page-composition, building-blocks, and page-templates proposals and consumes what they build rather than duplicating them. Drafted from the Itinera / Atlas-MES build (test app ako/MxcliTest1). Two corrections vs the original draft, verified against the codebase: - all chart types (incl. Line/Bubble/Heatmap/TimeSeries) are MDL-authorable today; the "stick to the authorable four" note was stale. - the two P0 warm-loop tooling bugs it listed are now fixed (PR #13), so those rows are marked done. Regenerates the proposals README index. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4 --- .../PROPOSAL_atlas_design_system.md | 486 ++++++++++++++++++ docs/11-proposals/README.md | 5 +- 2 files changed, 489 insertions(+), 2 deletions(-) create mode 100644 docs/11-proposals/PROPOSAL_atlas_design_system.md diff --git a/docs/11-proposals/PROPOSAL_atlas_design_system.md b/docs/11-proposals/PROPOSAL_atlas_design_system.md new file mode 100644 index 000000000..254dafb46 --- /dev/null +++ b/docs/11-proposals/PROPOSAL_atlas_design_system.md @@ -0,0 +1,486 @@ +--- +title: Atlas Design System — a skill for visually appealing Mendix apps +status: proposed +date: 2026-07-24 +related: + - page-styling-support.md + - show-describe-building-blocks.md + - PROPOSAL_mxcli_dev_warm_loop.md + - PR #13 (P0 warm-loop fixes) +--- + +# Atlas Design System — a skill for visually appealing Mendix apps + +> Drafted from the Itinera travel-planner build (test app `ako/MxcliTest1`). This is a +> **design-system / skill layer**, not new infrastructure — it sits *on top of* four existing +> proposals and consumes what they build. + +## Overview + +mxcli can generate a fully-functional Mendix app, but the default output looks **bland** — it leans +on raw Atlas defaults plus ad-hoc SCSS. Reaching the polish of a hand-designed HTML artifact is +possible but currently costs a day of manual iteration, fighting Atlas specificity, and +re-discovering the same gotchas. + +The Itinera build proved a **repeatable method** for closing that gap. This proposal captures it as +a skill so a generated app reaches "designed product" quality *by default* — the way +`artifact-design` does for standalone HTML and `dataviz` does for charts. + +**Scope boundary:** `atlas-design` is the *taste + workflow* layer. It does **not** re-specify the +styling mechanics, composition primitives, or building-block/template introspection — those are the +four proposals below. It *uses* them and adds the design system, the Atlas-first method, the recipe +library, the gotchas catalog, and the verify loop. + +--- + +## Relationship to existing proposals (reconciliation) + +This proposal deliberately **defers** to and **depends on** work already proposed. It should not +duplicate any of it. + +| Existing proposal | Status | What it owns | What `atlas-design` adds on top | +|---|---|---|---| +| `page-styling-support.md` | partial (Phase 1 done) | the 4 styling channels: `class`, inline `style`, `DynamicClasses`, typed `designproperties` | *which* classes/tokens to use and *when* (the Atlas vocabulary + palette method) | +| `proposal_page_composition.md` | proposed (fragments impl'd) | `define/use fragment`, `alter page`, partial updates, **parameterized fragments (future)** | ships the recipe library *as* fragments; designs recipes to migrate to parameterized fragments | +| `show-describe-building-blocks.md` | proposed (name-list only today — content unreadable) | `Forms$BuildingBlock` **read** (widget tree) → **instantiate** (`use`) → **author** (`create`) | uses Building Blocks as the eventual native home for recipes; maps Atlas blocks → our recipes; see the "what's needed" spec below | +| `show-describe-page-templates.md` | proposed (list-only today) | `Forms$PageTemplate` introspection | the page-template → screen map (Detail_Cards, Grid_Card, Dashboard_*) | + +If any of these advance, `atlas-design` should shrink accordingly (e.g., once `use building block` +lands, the `.mdl`/fragment recipe library becomes a thin adapter over native Building Blocks). + +--- + +## The core insight: be **Atlas-first** + +Our first pass hand-rolled `.panel` / `.trip-card` / `.stat` that **partly reinvented what Atlas +already ships**. Atlas exposes a rich appearance system reachable from MDL today via `class:` (Phase +1 of `page-styling-support` is done), with more idiomatic typed `designproperties` coming. + +### Atlas appearance vocabulary (from `atlas_core/web/design-properties.json`, verified in-project) + +| Concern | Atlas classes (apply via `class:`) | +|---|---| +| **Cards** | `card`, `cards` (+ Card-style variants) — real CSS (`.card` = 19 rules) | +| **Backgrounds** | `background-{default,main,primary,secondary,success,warning,danger}` | +| **Buttons** | `btn-{primary,secondary,success,warning,danger}`, `btn-{lg,sm,bordered,block,icon-right,icon-top}` | +| **Flex / align** | `flex-{row,column,nowrap,items-grow,items-shrink}`, `align-x-{left,center,right,between,around,evenly}`, `align-y-*` | +| **Spacing utils** | `spacing-{outer,inner}-{top,right,bottom,left}[-medium|-large|-none]` | +| **Borders / overflow** | `div-border-toggle-{all,top,…,none}`, `div-overflow-{auto,hidden,visible}`, Border radius/color/style/width | +| **Elevation** | `Shadow` toggle | +| **Data grids** | `datagrid-{bordered,hover,striped,lined,lg,sm}` | +| **Group boxes** | `groupbox-{primary,danger,secondary,callout}` | + +### Atlas page templates (`Forms$PageTemplate`, surfaced from `Atlas_Web_Content`, 46 pages) +Several map 1:1 onto what we hand-built: **`Detail_Cards` + `Detail_Timeline`** ≈ our detail page; +**`Dashboard_Status` + `Grid_Card`** ≈ our overview. `Grid_Card`, `List_Status`, `List_MasterDetail`, +`Dashboard_*`, `Wizard_Form`, `Tabs_Card` are canonical compositions to mirror. + +### Atlas Building Blocks (`Forms$BuildingBlock`, 233 across the team's test projects) +The Mendix-native "card/title recipe library": reusable widget compositions **copied** onto pages +(templates, not runtime components — dragging one in *deep-copies* its widget tree; there is no live +link afterwards), with preview thumbnails and categories. This is the eventual native home for our +recipes. + +#### Precise current state (verified in mxcli source) +"Can I create pages *with* Building Blocks today?" — **No.** Building Blocks are readable at the +name level only and cannot be inspected, instantiated, or authored via MDL: + +| Layer | State | Evidence | +|---|---|---| +| Go type + reader (`ListBuildingBlocks()`) | ✅ present — used by the project-tree TUI, `examples/read_project`, and exposed (unused) on the backend interface | `sdk/pages/pages.go`, `sdk/mpr/reader_types.go`, `mdl/backend/page.go` | +| Parser | ⚠️ reads **Name + Documentation only** — *not* the widget tree | `sdk/mpr/parser_misc.go` (`parseBuildingBlock`) | +| `SHOW` / `DESCRIBE BUILDING BLOCK` | ❌ `cmd_describe.go` **explicitly excludes** them | `cmd/mxcli/cmd_describe.go` (`unitTypeToDescribe`) | +| Grammar / AST / visitor / executor | ❌ none | grep `mdl/grammar`, `mdl/ast`, `mdl/visitor`, `mdl/executor` | +| Instantiate onto a page / author a new one | ❌ no syntax | — | + +So mxcli can list building-block names but can't read their content, describe them, copy one onto a +page, or create one. (`show-describe-building-blocks.md` is `status: proposed`.) + +#### What "create pages with Building Blocks" actually requires (three capabilities, in order) +1. **Read their content** — extend the widget-tree reader (a Building Block carries the *same* + `widgets: []` tree as `Forms$Page` / `Forms$Snippet`) to `Forms$BuildingBlock`, and surface it via + `SHOW BUILDING BLOCKS` (name, module, category, platform, preview) + `DESCRIBE BUILDING BLOCK + Mod.Name` (round-trippable MDL). Note: the reusable widget-tree logic already lives in the + executor (`parseRawWidget` / `getSnippetWidgetsFromRaw` over `Backend.GetRawUnit`, in + `mdl/executor/cmd_pages_describe.go`), not in `sdk/mpr` — that is what to reuse. Without this you + can't discover-then-reuse what a project already ships. **This is the prerequisite for everything + else.** +2. **Instantiate onto a page** — `USE BUILDING BLOCK Mod.Name [prefix 'p_']` inside a page/container + that **deep-copies** the block's widget tree in. Mechanically this is *fragment expansion sourced + from a persisted document* instead of a script-scoped `define fragment` — the copy semantics, + prefix/name-collision handling, and "no live link" behaviour are identical, so it can reuse the + fragment-expansion machinery. This is the capability that makes "compose a page from pre-built + sections" real. +3. **Author new ones (optional)** — `CREATE BUILDING BLOCK Mod.Name { widgets }` so generated apps + *contribute* reusable blocks back into the Studio-Pro toolbox (category, platform, preview + thumbnail). Lower priority than read + instantiate. + +**Why this matters for `atlas-design`:** because a Building Block is a *copy template*, our recipe +library maps onto it 1:1 (a recipe is also a copied widget shape). Once (1)+(2) land, the +`.mdl`/fragment recipes become a thin adapter over native Building Blocks *and* become visible in +Studio Pro — the ideal end-state. Until then, recipes ship as fragments + `.mdl` fill-in (below). + +**Rule of thumb — reach *down* the stack first:** need a card? `class:'card'` before a `.panel` +rule. Brand blue on buttons? `--brand-primary` before overriding `.btn-primary`. Custom CSS is the +**last** resort, for identity only. + +--- + +## Findings from live testing (this app, mxcli `b990548`) + +Ran a controlled experiment on the running app: a page of **pure Atlas classes, zero custom CSS**, +authored purely with mxcli's `class:` property. Result — **the Atlas-first thesis holds**: + +| Authored via `class:` | Rendered | +|---|---| +| `card` + `spacing-inner-large` | real Atlas card (surface bg, border, radius, padding) ✅ | +| `background-primary` | **the app's azure** — the Atlas utility inherited our retuned `--brand-primary` ✅ | +| `flex-row` + `align-x-between` | children spread left/right ✅ | +| `buttonstyle: primary`, `btn-lg` (class), `btn-bordered` (class) | solid / large / outlined Atlas buttons ✅ | + +**Confirmed for the proposal:** +1. **Raw `class:` strings are sufficient today** — `page-styling-support` Phase 1 (`class`) already renders + the full Atlas appearance vocabulary. The typed `designproperties` channel is **not required for the + visual result** (it matters only for round-tripping into Studio Pro's Appearance tab). → recipes can + ship on `class:` now; `designproperties` support is a nicety, not a blocker. +2. **Brand tokens propagate *down* into Atlas utilities** — `background-primary`/`btn-primary` resolve to + our `--brand-primary`. This validates the layered model: retune Layer 1 tokens and Layer 0 Atlas + classes follow for free. Strong argument to **delete** the hand-rolled `.panel`/`.trip-card`/`.stat`/ + `.insight-card` and use `class:'card …'`, keeping custom SCSS only for identity (mono type, pills, + timeline spine, elevation curve). + +**Tooling finding for the mxcli session (a real bug — now fixed):** +- Under `run --local --watch`, a **model change that added a page and repointed the home** hot-applied + "via restart, client re-bundled (gen 2)" but then **`/dist/index.js` 404'd** → the app served only the + `