# µFrame Dynamic Templates — Making Rich UIs Live on NomadNet

## Addendum to the µFrame Design Document (v3)

---

## 1. The NomadNet Dynamic Page Model

Understanding how NomadNet serves dynamic pages is essential to
understanding how µFrame templates become live applications.

### How it works

NomadNet has a simple but powerful execution model, analogous to
CGI on the early web:

```
  Client                             Node Server
  ──────                             ───────────
  1. Browse to /page/dashboard.mu
                        ───────────▶
                                     2. Is dashboard.mu executable?
                                        YES → run it
                                        NO  → send contents as-is

                                     3. Execute: #!/usr/bin/env python3
                                        Script prints Micron to stdout

                                     4. Capture stdout → send to client
                        ◀───────────
  5. Render Micron in terminal
```

Key mechanics:

- A `.mu` file without the execute bit is **static** — NomadNet
  sends its contents directly to the browsing client
- A `.mu` file with the execute bit set is **dynamic** — NomadNet
  runs it as a subprocess and serves whatever it prints to stdout
- The shebang line (`#!/usr/bin/env python3`) determines the
  interpreter — Python, Bash, Lua, Rust, anything that runs
- The script must **terminate** — it cannot wait for input or
  run indefinitely
- Cache behavior is controlled via a header line: `#!c=0` means
  never cache (always re-execute), `#!c=300` means cache for 5 min

### Form data flow

Micron form fields (`\`<field\`placeholder>`, `\`<^|group|val\`label>`,
etc.) collect user input. When the user clicks a link on a page
that contains form fields, the field data is submitted along with
the link request:

```
  Page A (has form fields + a submit link)

  ┌───────────────────────────────────────────────┐
  │  Name: `<24|name`Enter name...>               │
  │  Role: `<^|role|admin`Admin> `<^|role|user`User> │
  │                                               │
  │        `[Submit`:/page/handle.mu]              │
  └───────────────────────────────────────────────┘

  User fills in "Alice", selects "Admin", clicks Submit
                            │
                            ▼
  Page B (handle.mu) — receives field data via environment
  variables, generates a response page with Micron output
```

The submitted field data is passed to the executable script
through environment variables in the format:

```
  FIELD_name=Alice
  FIELD_role=admin
```

Or via stdin as a URL-encoded or structured data payload
(implementation varies by NomadNet version). The executable
script reads these values and uses them to generate its output.

---

## 2. µFrame's Dynamic Compilation Model

Here is the key insight: **µFrame doesn't just emit static
Micron text — it can compile `.uf` templates into executable
Python scripts that generate Micron at request time.**

This gives us three output modes:

```
  .uf source ──▶ Parser ──▶ IR ──┬──▶ Plain ASCII    (static preview)
                                 ├──▶ Static .mu      (static page)
                                 └──▶ Dynamic .mu     (executable script)
                                       │
                                       ▼
                                 #!/usr/bin/env python3
                                 # Auto-generated by µFrame
                                 # from: dashboard.uf
                                 import os, sys, json, subprocess
                                 ...
                                 print(rendered_micron)
```

The dynamic output is a self-contained Python script with:
- The µFrame rendering engine embedded (or imported)
- Data-fetching hooks that run at request time
- Form field processing from environment variables
- Conditional rendering based on submitted data
- The full ASCII art + Micron generation pipeline

### The three modes compared

```
  ┌──────────────────────────────────────────────────────────────┐
  │                     µFrame Output Modes                      │
  ├────────────────┬───────────────┬─────────────────────────────┤
  │ Plain ASCII    │ Static .mu    │ Dynamic .mu                 │
  ├────────────────┼───────────────┼─────────────────────────────┤
  │ Box-drawing    │ Box-drawing   │ Box-drawing                 │
  │ Block chars    │ Block chars   │ Block chars                 │
  │ Braille        │ Braille       │ Braille                     │
  │                │ + Color       │ + Color                     │
  │                │ + Bold/italic │ + Bold/italic               │
  │                │ + Links       │ + Links                     │
  │                │ + Form fields │ + LIVE form fields           │
  │                │               │ + Server-side data binding   │
  │                │               │ + Conditional rendering      │
  │                │               │ + Form submission handling   │
  │                │               │ + System data at render time │
  │                │               │ + State persistence          │
  ├────────────────┼───────────────┼─────────────────────────────┤
  │ Local terminal │ NomadNet page │ NomadNet live application   │
  │ preview        │ (cached)      │ (re-executed per request)   │
  └────────────────┴───────────────┴─────────────────────────────┘
```

---

## 3. DSL Extensions for Dynamic Behavior

### 3.1 Data Sources — `source` blocks

A `source` block declares where live data comes from. At render
time, the generated script executes the source and binds the
result to a variable.

```
# Shell command — output captured as string
source cpu_pct : shell "grep 'cpu ' /proc/stat | awk '{print int(($2+$4)*100/($2+$4+$5))}'"
source mem_pct : shell "free | awk '/Mem/{print int($3/$2*100)}'"
source uptime  : shell "uptime -p"
source peers   : shell "rnstatus -j | python3 -c 'import sys,json; d=json.load(sys.stdin); print(len(d.get(\"peers\",[]))); '"

# File read — contents loaded as string or parsed as JSON
source motd    : file "/etc/motd"
source config  : json "/home/node/.nomadnetwork/config.json"

# Python expression — evaluated inline (available: datetime, timedelta, secrets, os, json)
source timestamp : python "datetime.now().strftime('%Y-%m-%d %H:%M')"
source rand_hex  : python "secrets.token_hex(4)"
source uptime    : python "str(timedelta(seconds=12345))"
source hostname  : python "os.uname().nodename"

# RNS/Reticulum API — direct integration
source peer_list : rns "peers"
source node_info : rns "identity"
```

Sources are resolved **at page render time** — every time a
client requests the page, the commands run fresh.

Usage in templates:

```
gauge "CPU" $cpu_pct 100 28 warn=75 crit=90
gauge "MEM" $mem_pct 100 28 warn=80 crit=95
label "Uptime" "$uptime"
label "Peers" "$peers active"
text "Last updated: $timestamp"
```

### 3.2 Form Handling — `on_submit` blocks

An `on_submit` block defines what happens when a form is
submitted. It receives field values and controls what the
page renders in response.

```
page "Search" 64

  form "search"
    field "query" 30 "Enter search term..."
    radio "scope" "Local" | "Network" | "All"
    button "Search" "/page/search.mu"

  on_submit "search"
    # $query and $scope are now populated from submitted form data
    source results : shell "search_index.py '$query' --scope '$scope'"

    heading 2 "Results for: $query"

    if $results
      text "$results"
    else
      text "No results found."
```

The generated Python script handles this as:

```python
#!/usr/bin/env python3
#!c=0
import os, subprocess

# Read submitted form data
query = os.environ.get("FIELD_query", "")
scope = os.environ.get("FIELD_scope", "Local")

if query:
    # Form was submitted — render results
    results = subprocess.check_output(
        ["search_index.py", query, "--scope", scope]
    ).decode().strip()
    # ... render results template with Micron ...
else:
    # No submission — render the form
    # ... render form template with Micron ...
```

### 3.3 Conditional Rendering — `if` / `else` / `elif`

```
source disk_pct : shell "df / | awk 'NR==2{print int($5)}'"

if $disk_pct > 90
  box heavy "DISK CRITICAL"
    color f00
    gauge "Disk" $disk_pct 100 40 crit=90
    text "@bold{@color{f00}{Immediate action required!}}"
elif $disk_pct > 75
  box light "Disk Warning"
    color ff0
    gauge "Disk" $disk_pct 100 40 warn=75
else
  gauge "Disk" $disk_pct 100 40
```

### 3.4 Iteration — `for` loops

```
source peer_json : shell "rnstatus --json-peers"

heading 2 "Active Peers"

for peer in $peer_json
  row 2
    col 30
      text "$peer.name"
    col 10
      status "$peer.name" $peer.state
    col 10
      text "$peer.latency"
```

The `for` construct works with JSON arrays or newline-delimited
text from shell commands.

### 3.5 State Persistence — `state` blocks

Since each page request is a fresh script execution, state must
be stored externally. µFrame provides a simple key-value store
backed by a JSON file on the node:

```
state "counter" "/tmp/uframe_counter.json"

# Read
let visits = $counter.visits || 0

# Write (increments on each page load)
set counter.visits = $visits + 1

text "This page has been viewed $counter.visits times."
```

For form-driven state (e.g., a guestbook):

```
state "guestbook" "/var/nomadnet/guestbook.json"

form "sign"
  field "name" 20 "Your name..."
  field "message" 40 "Your message..."
  button "Sign" "/page/guestbook.mu"

on_submit "sign"
  append guestbook.entries { name: $name, message: $message, time: $timestamp }
  text "@color{0f0}{Thanks, $name! Your message has been saved.}"

heading 2 "Guestbook ($guestbook.entries.length entries)"

for entry in $guestbook.entries
  box light
    text "@bold{$entry.name} — @italic{$entry.time}"
    text "$entry.message"
  spacer
```

### 3.6 Page Navigation with Data — `link` with parameters

Links can pass data to the target page via query-style encoding:

```
# Simple navigation
link "Home" "/page/index.mu"

# Navigation with parameters
link "View Peer $peer.name" "/page/peer_detail.mu?hash=$peer.hash"

# In the target page, access with:
source peer_hash : param "hash"
```

### 3.7 Cache Control

```
page "Dashboard" 64
  cache 0              # never cache — always re-execute
  # cache 60           # cache for 60 seconds
  # cache none         # alias for 0

  source cpu : shell "..."
  ...
```

Translates to the Micron header `#!c=0` in the first line of output.

---

## 4. Compilation Pipeline — .uf to Executable .mu

### 4.1 What the compiler generates

A `.uf` file with dynamic features compiles into a Python script
that:

1. Sets the shebang and cache header
2. Imports required modules + the `uframe` package
3. Defines runtime helpers (`_shell`, `_read_file`, `_read_json`, etc.)
4. Executes source commands and evaluates conditionals/loops
5. Dynamically builds a `.uf` source string with resolved variables
6. Compiles that source with `uframe.compile()` at runtime
7. Prints the resulting Micron to stdout

```python
#!/usr/bin/env python3
# Auto-generated by uFrame
# Do not edit — regenerate with: uframe compile <source>.uf

import os, sys, json, subprocess, datetime, secrets, shlex
from datetime import datetime as _dt_cls, timedelta

# ─── Runtime Helpers ─────────────────────────────────────────

def _shell(cmd, timeout=5):
    """Execute shell command, return stdout."""
    try:
        return subprocess.check_output(cmd, shell=True, timeout=timeout).decode().strip()
    except Exception:
        return ""

def _read_file(path):
    """Read file contents."""
    # ...

def _read_json(path):
    """Read and parse JSON file."""
    # ...

def _get_field(name, default=""):
    """Read submitted form field from environment."""
    return os.environ.get(f"FIELD_{name}", default)

def _get_param(name, default=""):
    """Read URL parameter."""
    return os.environ.get(f"PARAM_{name}",
           os.environ.get(f"var_{name}", default))

def _load_state(path):
    """Load state from JSON file."""
    # ...

def _save_state(path, data):
    """Save state to JSON file."""
    # ...

def _iter(val):
    """Make a value iterable for for-loops."""
    # handles lists, dicts, newline-delimited strings

# ─── µFrame Compile ──────────────────────────────────────────

import uframe

# ─── Page Logic ──────────────────────────────────────────────

_cache_seconds = 0

_uf_source_parts = []
cpu_pct = eval('secrets.randbelow(60) + 20', {'datetime': _dt_cls, ...})
timestamp = eval("datetime.now().strftime('%H:%M:%S')", {'datetime': _dt_cls, ...})

_uf_source_parts.append(f'heading 1 "Resources"')
_uf_source_parts.append(f'gauge "CPU" {cpu_pct} 100 28 warn=75.0 crit=90.0')
_uf_source_parts.append(f'text "Updated: {timestamp}"')

if cpu_pct > 90:
    _uf_source_parts.append(f'text "ALERT: CPU critical"')

# ─── Render & Output ─────────────────────────────────────────

_uf_source = f'''page "Live Status" 60
''' + "\n".join(_uf_source_parts)

result = uframe.compile(_uf_source, width=60)

if _cache_seconds >= 0:
    print(f"#!c={_cache_seconds}")
print(result.micron)
```

The key insight: the generated script **rebuilds `.uf` source** with
live data substituted in, then compiles it with the full µFrame
pipeline. This means every layout feature (boxes, gauges, tables,
sparklines) works identically in both static and dynamic pages.

### 4.2 CLI usage

```bash
# Compile to dynamic executable .mu
uframe compile dashboard.uf --out dashboard.mu
chmod +x dashboard.mu

# Compile and deploy in one step
uframe deploy dashboard.uf
# → renders, sets +x, copies to ~/.nomadnetwork/storage/pages/

# Compile with embedded vs. imported runtime
uframe compile dashboard.uf --embed    # single self-contained file
uframe compile dashboard.uf --import   # requires uframe_runtime.py on node
```

### 4.3 Compilation modes

```
┌────────────────────────────────────────────────────────────────┐
│                   µFrame Compilation Modes                     │
├────────────────┬───────────────┬───────────────────────────────┤
│ uframe render  │ uframe render │ uframe compile                │
│   --ascii      │   --micron    │                               │
├────────────────┼───────────────┼───────────────────────────────┤
│ Static ASCII   │ Static .mu    │ Executable .mu (Python)       │
│ to stdout      │ file          │ file with +x                  │
├────────────────┼───────────────┼───────────────────────────────┤
│ All values     │ All values    │ source{} values fetched       │
│ resolved at    │ resolved at   │ at request time               │
│ render time    │ render time   │                               │
│                │               │ Form fields become live       │
│                │               │ on_submit{} blocks active     │
│                │               │ if/for evaluated per request  │
│                │               │ State persists across visits  │
└────────────────┴───────────────┴───────────────────────────────┘
```

---

## 5. Complete Dynamic Example

### 5.1 Source — `search_node.uf`

```
page "Node Search" 64
  cache 0

  source timestamp : python "datetime.now().strftime('%H:%M:%S')"
  source peer_count : shell "rnstatus 2>/dev/null | grep -c 'Peer'"
  state "history" "/var/nomadnet/search_history.json"

  box double "Node Search"
    align center
    text "Find peers and pages on the Reticulum mesh"
    text "@italic{$peer_count peers reachable · updated $timestamp}"

  spacer

  form "search"
    field "query" 30 "Search term..."
    radio "type" "Nodes" | "Pages" | "Files"
    checkbox "cache" "Include cached results"
    button "Search" "/page/search_node.mu"

  on_submit "search"
    # Log the search
    append history.queries { q: $query, type: $type, time: $timestamp }

    source results : shell "mesh_search.py '$query' --type '$type'"
    source result_count : python "len('''$results'''.strip().splitlines())"

    divider light

    heading 2 "Results for \"$query\" ($result_count found)"

    if $result_count > 0
      for line in $results
        source parts : python "'''$line'''.split('|')"
        row 1
          col 28
            link "$parts.0" "/page/detail.mu?hash=$parts.1"
          col 8
            text "$parts.2"
          col 10
            status "$parts.0" $parts.3
    else
      spacer
      text "@center{@color{ff0}{No results found for \"$query\"}}"
      spacer

    divider light
    heading 3 "Recent Searches"

    for entry in $history.queries[-5:]
      text "  $entry.time  $entry.q ($entry.type)"

  divider heavy
  text "@center{@italic{Relay Alpha-7 · $timestamp}}"
```

### 5.2 What the client sees

**Before submission** (form is empty):

```
╔══ Node Search ═══════════════════════════════════════════════╗
║            Find peers and pages on the Reticulum mesh        ║
║            7 peers reachable · updated 14:32:07              ║
╚══════════════════════════════════════════════════════════════╝

  Search: [ Search term...___________________ ]
  Type:   (•) Nodes   ( ) Pages   ( ) Files
          [ ] Include cached results

                            `[`!Search`!`:/page/search_node.mu]

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
                   Relay Alpha-7 · 14:32:07
```

**After submitting "relay"** (script re-executes with FIELD_query=relay):

```
╔══ Node Search ═══════════════════════════════════════════════╗
║            Find peers and pages on the Reticulum mesh        ║
║            7 peers reachable · updated 14:32:15              ║
╚══════════════════════════════════════════════════════════════╝

  Search: [ relay__________________________ ]
  Type:   (•) Nodes   ( ) Pages   ( ) Files
          [ ] Include cached results

                            `[`!Search`!`:/page/search_node.mu]

  ──────────────────────────────────────────────────────────────

  >> Results for "relay" (3 found)

  `F0cfRelay-East`f             2 hops     `F0f0●`f online
  `F0cfRelay-South`f            4 hops     `F0f0●`f online
  `F0cfRelay-Backup`f           6 hops     `Fff0◐`f degraded

  ──────────────────────────────────────────────────────────────

  >>> Recent Searches
    14:32:15  relay (Nodes)
    14:28:44  bridge (Pages)
    14:25:01  firmware (Files)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
                   Relay Alpha-7 · 14:32:15
```

The form fields retain submitted values, results appear below,
and the search history persists across visits via the state file.
Every piece of box-drawing, every colored indicator, every braille
sparkline renders identically in both ASCII preview and live Micron.

---

## 6. Dynamic Patterns — A Cookbook

### 6.1 Live Dashboard (auto-refresh via cache=0)

```
page "Status" 64
  cache 0

  source cpu : python "secrets.randbelow(60) + 20"
  source mem : python "secrets.randbelow(40) + 50"
  source uptime : python "str(timedelta(seconds=secrets.randbelow(86400)))"
  source timestamp : python "datetime.now().strftime('%H:%M:%S')"

  box heavy "System Status"
    row 2
      gauge "CPU" $cpu 100 28 warn=75 crit=90
      gauge "MEM" $mem 100 28 warn=80 crit=95
    spacer
    label "Uptime" "$uptime"
    label "Updated" "$timestamp"

  text "@center{@italic{Press Ctrl+R to refresh}}"
```

Client hits the page → script runs → evaluates sources →
renders gauges with live data → client sees it.
Ctrl+R re-requests → fresh execution → updated values.

On a full Linux node, replace the python sources with shell commands
to read real system data:

```
source cpu : shell "grep 'cpu ' /proc/stat | awk '{print int(($2+$4)*100/($2+$4+$5))}'"
source mem : shell "free | awk '/Mem/{print int($3/$2*100)}'"
source uptime : shell "uptime -p"
```

### 6.2 Guestbook with Persistent State

```
page "Guestbook" 64
  cache 0

  state "gb" "/var/nomadnet/guestbook.json"
  source timestamp : python "datetime.now().strftime('%Y-%m-%d %H:%M')"

  heading 1 "Guestbook"

  form "sign"
    field "name" 20 "Your name"
    field "msg" 40 "Leave a message..."
    button "Sign" "/page/guestbook.mu"

  on_submit "sign"
    if $name && $msg
      prepend gb.entries { name: $name, msg: $msg, time: $timestamp }
      text "@color{0f0}{✓ Thanks, $name!}"

  divider light

  for entry in $gb.entries[:20]
    box rounded
      text "@bold{$entry.name}  @italic{@color{888}{$entry.time}}"
      text "$entry.msg"
    spacer
```

### 6.3 Multi-Page Wizard with Navigation

```
# Page 1: setup.mu
page "Setup Wizard — Step 1" 64
  cache 0

  heading 1 "Network Configuration"
  form "net"
    field "interface" 20 "eth0"
    radio "mode" "Auto" | "Manual" | "Mesh Only"
    button "Next →" "/page/setup_2.mu"

# Page 2: setup_2.mu
page "Setup Wizard — Step 2" 64
  cache 0

  source iface : param "interface"   # or field from previous page
  source mode  : param "mode"

  heading 1 "Confirm Settings"
  label "Interface" "$iface"
  label "Mode" "$mode"

  form "confirm"
    checkbox "apply_now" "Apply immediately"
    button "← Back" "/page/setup.mu"
    button "Finish ✓" "/page/setup_done.mu?interface=$iface&mode=$mode"
```

### 6.4 Chat Room (community pattern)

```
page "Chat" 64
  cache 0

  state "chat" "/var/nomadnet/chatlog.json"
  source timestamp : python "datetime.now().strftime('%H:%M')"

  heading 1 "Node Chat"

  # Display last 15 messages
  for msg in $chat.messages[-15:]
    text "@bold{@color{$msg.color}{$msg.nick}}  @color{888}{$msg.time}"
    text "  $msg.text"

  divider light

  form "send"
    field "nick" 12 "Nickname"
    field "text" 40 "Type message..."
    button "Send" "/page/chat.mu"

  on_submit "send"
    if $nick && $text
      source color : python "format(hash('$nick')%4095,'03x')"
      append chat.messages { nick: $nick, text: $text, time: $timestamp, color: $color }

  text "@center{@italic{@color{888}{Ctrl+R to refresh · $chat.messages.length messages}}}"
```

### 6.5 Interactive Data Explorer

```
page "Peer Explorer" 64
  cache 0

  source peers_json : shell "rnstatus --json 2>/dev/null"
  source selected : param "hash"

  heading 1 "Peer Explorer"

  table "Peers"
    columns "Name" 24 | "Hops" 6 | "RTT" 8 | "Status" 10
    for peer in $peers_json.peers
      row "$peer.name" | "$peer.hops" | "$peer.rtt" | "$peer.status"

  if $selected
    divider heavy
    source detail : shell "rnstatus --peer $selected --json 2>/dev/null"

    box double "Peer Detail: $detail.name"
      label "Hash"      "$detail.hash"
      label "Address"   "$detail.address"
      label "Hops"      "$detail.hops"
      label "Latency"   "$detail.rtt"
      label "Last Seen" "$detail.last_seen"
      label "Transport" "$detail.transport"

      sparkline "Latency (24h)" $detail.latency_history 40

      row 2
        link "Ping" "/page/action.mu?cmd=ping&hash=$detail.hash"
        link "Trace" "/page/action.mu?cmd=trace&hash=$detail.hash"
        link "Browse" "$detail.hash:/page/index.mu"
```

---

## 7. Security Considerations

Dynamic pages execute code on the node server. µFrame enforces:

- **Shell command sanitization**: all `$variable` values interpolated
  into shell commands are escaped with `shlex.quote()` to prevent
  injection
- **State file isolation**: state files are restricted to a
  configurable directory (default: `/var/nomadnet/uframe/`)
- **Execution timeout**: all shell sources have a default 5-second
  timeout, configurable per source
- **No network egress by default**: source commands run in the
  node's local context — they can read local system data but
  µFrame does not add network capabilities beyond what the
  scripts themselves invoke
- **Input validation**: field values are length-limited and
  sanitized before use in sources or state operations

```
# In the DSL, explicit sanitization:
source result : shell "search.py" --arg $query --sanitize
  timeout 10
  max_length 256
```

---

## 8. Architecture Summary

```
                         ┌──────────────────────────────┐
                         │         .uf Source            │
                         │  (layout + sources + forms    │
                         │   + conditionals + state)     │
                         └──────────────┬───────────────┘
                                        │
                                   ┌────▼────┐
                                   │  Parse  │
                                   └────┬────┘
                                        │
                                   ┌────▼────┐
                                   │   IR    │
                                   │  Tree   │
                                   └──┬───┬──┘
                                      │   │
                       ┌──────────────┘   └────────────────┐
                       │                                   │
                ┌──────▼──────┐                    ┌───────▼───────┐
                │ render mode │                    │ compile mode  │
                │ (immediate) │                    │ (codegen)     │
                └──┬───────┬──┘                    └───────┬───────┘
                   │       │                               │
            ┌──────▼┐  ┌───▼─────┐                ┌───────▼────────┐
            │ ASCII │  │ Static  │                │ Executable .mu │
            │ stdout│  │ .mu file│                │ Python script  │
            └───────┘  └─────────┘                │ with embedded  │
                                                  │ runtime +      │
                                                  │ data sources + │
                                                  │ form handling  │
                                                  └───────┬────────┘
                                                          │
                                                     chmod +x
                                                     deploy to
                                                          │
                                                ┌─────────▼─────────┐
                                                │   NomadNet Node   │
                                                │  ~/.nomadnetwork/ │
                                                │  storage/pages/   │
                                                │                   │
                                                │  Client request → │
                                                │  Execute script → │
                                                │  Stdout = Micron  │
                                                │  with live data,  │
                                                │  rich ASCII art,  │
                                                │  color + forms    │
                                                └───────────────────┘
```

The dynamic model turns µFrame from a static template engine into a
**full application framework for NomadNet** — where the same DSL that
defines the visual layout also defines the data flow, user interaction,
and server-side logic. The ASCII art isn't decoration — it's the UI
of a live, interactive, decentralized application running over
encrypted mesh networks.
