Skip to main content

State Overview

WikiOnitViewer maintains the simplest state model among all wiki viewers: just one custom array plus inherited properties from the base class.
┌─────────────────────────────────────────────────────┐
│  State Inventory                                    │
├─────────────────────────────────────────────────────┤
│                                                     │
│  Own State:                                         │
│    sessions: OnitSession[]                          │
│                                                     │
│  Inherited State (from WikiBaseViewer):             │
│    container: HTMLElement | null                    │
│    projectSlug: string                              │
│    category: string                                 │
│    isWip: boolean                                   │
│    settings: WikiViewerSettings                     │
│    currentDocument: string                          │
│                                                     │
│  Total: 7 properties (6 inherited + 1 own)          │
│                                                     │
└─────────────────────────────────────────────────────┘

Sessions Array

The only state property unique to OnIt:
┌───────────────────────────────────────────────────────────────────────┐
│  SESSIONS ARRAY                                                       │
├───────────────────────────────────────────────────────────────────────┤
│                                                                       │
│  DECLARATION:                                                         │
│    private sessions: OnitSession[] = []                               │
│                                                                       │
│  CHARACTERISTICS:                                                     │
│  ├── Array of parsed session objects                                  │
│  ├── Sorted newest first (descending sortKey)                         │
│  ├── Populated during loadSessions()                                  │
│  └── Completely replaced on refresh()                                 │
│                                                                       │
└───────────────────────────────────────────────────────────────────────┘
Example Session:
┌───────────────────────────────────────────────────────────────────────┐
│  sessions[0] = {                                                      │
│                                                                       │
│    path:        "/full/path/2025-12-28-14-30-session.md"              │
│    name:        "2025-12-28-14-30-session.md"                         │
│    date:        "2025-12-28"                                          │
│    time:        "14:30"                                               │
│    sessionName: "session"                                             │
│    pattern:     3                                                     │
│    sortKey:     "2025-12-28T14:30:00"                                 │
│    status:      "active"                                              │
│                                                                       │
│  }                                                                    │
└───────────────────────────────────────────────────────────────────────┘

State Lifecycle

Initialization

┌─────────────────────────────────────────────────────┐
│  Initialization State Changes                       │
├─────────────────────────────────────────────────────┤
│                                                     │
│  BEFORE init():                                     │
│    container: null                                  │
│    sessions: []                                     │
│    isWip: true (default)                            │
│                                                     │
│       ↓ init(container, projectSlug, "onit")        │
│                                                     │
│  AFTER init():                                      │
│    container: HTMLElement (assigned)                │
│    sessions: [OnitSession, ...]                     │
│    isWip: true (unchanged)                          │
│    category: "onit"                                 │
│    settings: loaded from localStorage               │
│                                                     │
└─────────────────────────────────────────────────────┘

Toggle Transition

┌─────────────────────────────────────────────────────┐
│  WIP/Wiki Toggle Effect                             │
├─────────────────────────────────────────────────────┤
│                                                     │
│  WIP Mode:                                          │
│    isWip: true                                      │
│    sessions: [WIP sessions from wip/onit/]          │
│                                                     │
│       ↓ User clicks [Wiki] button                   │
│                                                     │
│  Wiki Mode:                                         │
│    isWip: false                                     │
│    sessions: [Wiki sessions from wiki/onit/]        │
│                                                     │
│  Note: Other properties unchanged                   │
│                                                     │
└─────────────────────────────────────────────────────┘

Refresh Cycle

┌─────────────────────────────────────────────────────┐
│  Refresh State Changes                              │
├─────────────────────────────────────────────────────┤
│                                                     │
│  BEFORE refresh():                                  │
│    sessions: [old data - may be stale]              │
│                                                     │
│       ↓ refresh() called                            │
│                                                     │
│  AFTER refresh():                                   │
│    sessions: [new data - fresh from filesystem]     │
│                                                     │
│  Note: Complete array replacement                   │
│        DOM fully re-rendered                        │
│        Accordion states LOST                        │
│                                                     │
└─────────────────────────────────────────────────────┘

State Dependencies

Path construction depends on three state properties:
┌───────────────────────────────────────────────────────────────────────┐
│  PATH CALCULATION (getBasePath)                                       │
├───────────────────────────────────────────────────────────────────────┤
│                                                                       │
│  BASE = "~/Library/Application Support/monolex/protocols/niia/work"   │
│                                                                       │
│  FORMULA:                                                             │
│    folder = isWip ? "wip" : "wiki"                                    │
│    path = "{base}/{projectSlug}/{folder}/{category}"                  │
│                                                                       │
│  EXAMPLE:                                                             │
│    projectSlug = "monolex-006"                                        │
│    isWip = true                                                       │
│    category = "onit"                                                  │
│                                                                       │
│    Result: ~/Library/.../work/monolex-006/wip/onit/                   │
│                                                                       │
│  Changing ANY dependency changes the filesystem path                  │
│  and thus the loaded sessions.                                        │
│                                                                       │
└───────────────────────────────────────────────────────────────────────┘

Unidirectional Data Flow

State flows in one direction only:
┌─────────────────────────────────────────────────────┐
│  Data Flow                                          │
├─────────────────────────────────────────────────────┤
│                                                     │
│  User Action (click toggle/refresh)                 │
│       ↓                                             │
│  Event Handler                                      │
│       ↓                                             │
│  State Update (isWip, sessions)                     │
│       ↓                                             │
│  Re-render (render() called)                        │
│       ↓                                             │
│  DOM Updated (content replaced)                     │
│       ↓                                             │
│  Event Listeners Attached (to new elements)         │
│       ↓                                             │
│  (Loop back to User Action)                         │
│                                                     │
│  No reverse flow: DOM → State                       │
│                                                     │
└─────────────────────────────────────────────────────┘

DOM vs JavaScript State

Clear separation between persistent state and ephemeral UI state: JavaScript State (this.*):
  • sessions: OnitSession[] (source of truth)
  • isWip: boolean
  • settings: ViewerSettings
  • Persists across renders
DOM State (in elements):
  • Accordion expanded/collapsed
  • Content loaded (data-loaded)
  • Arrow rotation
  • Scroll position
  • Lost on re-render
Relationship:
  • JS state is source of truth for data
  • DOM state is ephemeral (recreated on render)
  • Re-render regenerates DOM from JS state
  • No two-way binding

State Reset Pattern

Complete replacement on refresh:
┌───────────────────────────────────────────────────────────────────────┐
│  REFRESH PATTERN                                                      │
├───────────────────────────────────────────────────────────────────────┤
│                                                                       │
│  refresh()                                                            │
│    │                                                                  │
│    ├── await this.loadSessions()   ← REPLACES this.sessions           │
│    │                                                                  │
│    └── this.render()               ← Re-renders entire DOM            │
│                                                                       │
│  EFFECT:                                                              │
│  ├── No incremental updates                                           │
│  ├── No diffing/patching                                              │
│  ├── Guaranteed consistency                                           │
│  └── Accordion states lost                                            │
│                                                                       │
│  TRADE-OFFS:                                                          │
│  ├── Simplicity (SMPC principle)                                      │
│  ├── Easy to reason about                                             │
│  ├── Potential performance impact on large lists                      │
│  └── Loses UI state                                                   │
│                                                                       │
└───────────────────────────────────────────────────────────────────────┘

Memory Management

Automatic cleanup via garbage collection: On refresh():
  1. this.sessions = new array → Old array becomes unreachable
  2. Container content replaced → Old DOM nodes removed
  3. JavaScript GC cleans up old arrays
  4. Browser GC cleans up old DOM nodes
  5. Event listeners on old nodes auto-removed
No manual cleanup needed. No memory leaks from orphaned listeners.

Settings Management

User preferences loaded from localStorage:
┌───────────────────────────────────────────────────────────────────────┐
│  WIKI VIEWER SETTINGS                                                 │
├───────────────────────────────────────────────────────────────────────┤
│                                                                       │
│  INTERFACE:                                                           │
│  ┌───────────────────────────────────────────────────────────────┐    │
│  │  fontSize:    string    // "12"                               │    │
│  │  fontWeight:  string    // "300"                              │    │
│  │  lineHeight:  string    // "1.6"                              │    │
│  │  opacity:     string    // "75"                               │    │
│  │  fontFamily:  string    // "CodexMono, CodexMono EA"          │    │
│  └───────────────────────────────────────────────────────────────┘    │
│                                                                       │
│  LOADING:                                                             │
│    For each setting:                                                  │
│      value = localStorage.getItem("wikiViewer{Setting}") || default   │
│                                                                       │
│  DEFAULTS:                                                            │
│    fontSize   = "12"                                                  │
│    fontWeight = "300"                                                 │
│    lineHeight = "1.6"                                                 │
│    opacity    = "75"                                                  │
│    fontFamily = "CodexMono, CodexMono EA"                             │
│                                                                       │
│  Settings apply to entire viewer container via getViewerStyles()      │
│                                                                       │
└───────────────────────────────────────────────────────────────────────┘

State Comparison

OnIt has the simplest state model:
ViewerOwn State PropsTotal StateComplexity
OnIt17Simplest
Prepare28Low-Medium
Prove39Medium
Unified410Medium-High
Docs511Highest
Minimal state aligns with SMPC: simplicity over complexity.
THE CENTER
Simple state enables predictable behavior

Technical Credibility

Single source of truth pattern. Unidirectional data flow. TypeScript type safety via interfaces. Automatic garbage collection for memory management. No manual listener cleanup required.