# µFrame (Micronomicon) A declarative DSL and web IDE for building rich terminal UIs that publish as `.mu` pages to [NomadNet](https://github.com/markqvist/NomadNet) — a decentralized communication platform on the [Reticulum](https://github.com/markqvist/Reticulum) mesh network. Write structured layouts with box-drawing, gauges, tables, and forms in a simple DSL. Get both plain ASCII art (viewable in any terminal) and styled Micron markup (with colors, links, and interactive form fields) from the same source. ``` page "Dashboard" 60 ╔═ Relay Alpha ══════════════════╗ box double "Relay Alpha" ║ Reticulum Network Node ║ align center ╚════════════════════════════════╝ text "Reticulum Network Node" CPU ████████████████░░░░ 62% gauge "CPU" 62 100 28 warn=75 crit=90 MEM ██████████████████░░ 84% ⚠ gauge "MEM" 84 100 28 warn=80 crit=95 ┌──────────┬──────┬──────────┐ table "Routes" │Dest │Hops │Status │ columns "Dest" 10 | "Hops" 6 | ... ├──────────┼──────┼──────────┤ row "east" | "2" | "alive" │east │2 │● alive │ └──────────┴──────┴──────────┘ status "East Relay" online ● East Relay ``` --- ## Quick Start ### Web IDE ```bash # 1. Create directories mkdir -p ~/.nomadnetwork/storage/pages ~/.micron-editor/sources # 2. Backend cd backend python -m venv .venv && source .venv/bin/activate pip install -r requirements.txt PAGES_DIR=~/.nomadnetwork/storage/pages \ SOURCES_DIR=~/.micron-editor/sources \ uvicorn main:app --reload --port 8080 # 3. Frontend (separate terminal) cd frontend npm install npm run dev ``` Open http://localhost:5173 → **New Page** → **Examples** → pick a template. ### CLI ```bash cd backend && source .venv/bin/activate python -m uframe render page.uf # ASCII to stdout python -m uframe render page.uf --micron # Micron to stdout python -m uframe compile page.uf # → page.mu python -m uframe check page.uf # validate python -m uframe deploy page.uf # compile + copy to NomadNet pages ``` ### Docker ```bash # 1. Build the frontend cd frontend npm install npm run build cd .. # 2. Build and start all services docker compose up --build -d ``` This starts two containers: - **micronomicon** — the web IDE + API on - **nomadnet** — NomadNet node serving your published `.mu` pages Pages published through the IDE are written to a shared volume that NomadNet reads from. The Docker socket is mounted read-only so the IDE can restart NomadNet when needed. To follow logs: `docker compose logs -f` To stop: `docker compose down` To expose over Tailscale: `tailscale serve --bg https+insecure://localhost:8080` #### Deploy a page via CLI (into the running stack) ```bash cd backend && source .venv/bin/activate python -m uframe deploy page.uf --dest "$(docker volume inspect micronomicon_pages -f '{{.Mountpoint}}')" ``` Or use the web IDE at and click **Publish**. --- ## DSL Overview ### Layout ``` page "Title" [width] # root container box [light|heavy|double|rounded] "Title" # bordered panel row [gap] # horizontal split col [width] # column spacer [lines] # vertical space ``` ### Content ``` heading [1|2|3] "Text" # heading text "Hello @bold{world} @color{0f0}{green}" # text with inline modifiers label "Key" "Value" # key-value pair link "Click me" "/page/dest.mu" # clickable link divider [light|heavy|double] # horizontal rule ``` ### Data Visualization ``` gauge "CPU" 62 100 28 warn=75 crit=90 # ████████░░░░ 62% sparkline "Net" "1,3,5,8,7,5" 20 # ⣀⣤⣶⣿⣷⣤ braille chart status "Server" [online|offline|degraded] # ●○◐ indicator table "Routes" columns "Dest" 20 | "Hops" 6 row "east" | "2" ``` ### Forms ``` form "search" field "query" 30 "Search..." # text input radio "scope" "Local" | "Network" # radio buttons checkbox "cache" "Include cached" # checkbox button "Go" "/page/search.mu" # submit ``` ### Dynamic Pages ``` cache 0 # re-execute on every request source cpu : shell "cat /proc/loadavg" # live data if $cpu > 90 text "ALERT" for peer in $peers status "$peer.name" $peer.state state "visits" "/tmp/visits.json" # persistent store ``` ### Components ``` component stat(label, value, max) gauge "$label" $value $max 20 stat "CPU" 62 100 # reuse use std/dashboard # import standard library banner "My Node" "Mesh Network" # use library component ``` --- ## Architecture ``` .uf source → Parse → IR Tree → Measure → Layout → Paint → CharGrid ├→ ASCII (plain text) ├→ Micron (.mu with styles) └→ Script (dynamic: executable Python) ``` **Static pages**: `.uf` compiles to `.mu` (Micron markup). NomadNet serves the file directly. **Dynamic pages**: `.uf` with `source`/`if`/`for` compiles to an executable Python script. NomadNet detects the `+x` bit, runs the script on each request, and serves the stdout as Micron. Live system data, form handling, and state persistence all work through this model. --- ## API | Method | Path | Description | |--------|---------------------|-------------------------------------------------------| | POST | /api/compile | Compile `.uf` → `{ascii, micron, script, is_dynamic}` | | GET | /api/pages | List all pages with metadata | | GET | /api/pages/{name} | Read page source | | POST | /api/pages/{name} | Save `{source, publish}` — draft or publish | | DELETE | /api/pages/{name} | Delete page | | GET | /api/graph | Page link graph | | POST | /api/restart | Restart NomadNet container | --- ## Web IDE Features - **Split-pane editor** with µFrame syntax highlighting and live preview - **`/` command palette** — type `/` to insert any DSL primitive - **4 preview tabs** — ASCII | Micron (rendered) | Raw | Script (dynamic only) - **Examples dropdown** — 9 templates from Hello World to Dynamic Dashboard - **Pages dashboard** with Published / Draft / Orphan status badges - **Page graph** — React Flow visualization of inter-page links - **Keyboard shortcuts** — `Ctrl+S` save, `Ctrl+P` publish - **Backlink indicator** — shows which pages link to the current page --- ## Environment Variables | Variable | Default | Description | |----------------------|------------------|--------------------------------------| | `PAGES_DIR` | `/data/pages` | NomadNet pages directory | | `SOURCES_DIR` | `/data/sources` | µFrame source files directory | | `NOMADNET_CONTAINER` | `nomadnet` | Docker container name to restart | --- ## Tests ```bash cd backend && source .venv/bin/activate python -m pytest uframe/tests/ -v # 91 tests ``` --- ## References - [NomadNet](https://github.com/markqvist/NomadNet) — decentralized communication - [Reticulum](https://github.com/markqvist/Reticulum) — mesh networking stack - [Micron syntax](https://github.com/fr33n0w/micron-composer) — markup reference - [Design spec](docs/framework-design-v3.md) — full DSL design document - [Dynamic templates](docs/dynamic-templates.md) — dynamic page system spec