# uihp-challenges/uihp-challenges-april23 architecture

> Architecture diagram of the GitHub repository uihp-challenges/uihp-challenges-april23, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-27). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/uihp-challenges/uihp-challenges-april23
- Repository: https://github.com/uihp-challenges/uihp-challenges-april23

## Overview

1. This repo is a browser-only learning scaffold, not a production app. The architecture is a single static page in `challenges/index.html` plus one stylesheet and five alternative JavaScript entrypoints (`part1.js` through `part5.js`). There is no build step, no bundler, no backend, and no external data source.

2. The main architectural boundary is the browser itself: HTML creates the DOM, CSS creates the CSSOM, and JavaScript runs in the browser runtime with direct access to `document`, events, timers, and element properties. The code is about progressively moving from manual DOM edits to state-driven rendering.

3. `index.html` is the only entrypoint. It initially contains the view container and switches which lesson script runs by changing the `<script src>` from one part file to another. That means only one JS model is active at a time; the parts are not composed together.

4. `styles.css` is a separate presentation layer applied to the static DOM. It does not drive behavior; it only affects how the browser renders the elements that the JavaScript creates or updates.

5. Part 1 is the simplest UI loop: JavaScript queries existing DOM nodes, stores them in local variables, updates `textContent`, and wires an `input` event handler. The data flow is user input -> event handler -> JS variable -> DOM mutation. This is direct, imperative DOM manipulation.

6. Part 2 introduces one-way data binding. The important boundary becomes “data” versus “view”: event handlers update JS state, then a single `dataToView` function copies that state into DOM properties. A timer (`setInterval`) can force repeated view refreshes, so the view is treated as a projection of current state.

7. Part 3 shifts from selecting existing elements to creating them from a “virtual DOM” description. The UI is described as arrays of element metadata, then `convert` turns each description into a real DOM node. The view is now generated from data rather than manually edited, and the DOM is replaced as a whole on each update.

8. Part 4 generalizes composition. Instead of converting two hardcoded nodes, the code maps over an arbitrarily sized `vDOM` list to produce a list of element objects, then appends/replaces them in the document body. This is the repo’s flexible composition layer: list in, list out, render all.

9. Part 5 adds a shared state store and update hook. Data moves into a single `data` object, and `updateData(label, value)` becomes the only sanctioned write path. After any state change, `updateDOM` runs, so state changes and rendering are coupled through one boundary rather than scattered across event handlers.

10. Also in Part 5, rendering becomes incremental with a diffing/reconciliation step. `prevVDOM` preserves the previous virtual tree, `findDiff` compares it to the current tree, and only changed nodes are reconciled back into the actual DOM. The architecture here is “state store -> vDOM generation -> diff -> minimal DOM updates.”

11. The repo’s reusable conceptual pipeline is: browser event -> handler -> state update -> virtual description -> DOM conversion -> render. Each later part tightens that pipeline by reducing where state can change and how much of the DOM must be recreated.

12. There are no server, API, routing, persistence, or component-library boundaries here. The only meaningful external interfaces are standard browser APIs: DOM querying/creation, event handling, timers, and focus/selection behavior. That makes the project a pure client-side UI architecture exercise.

Main entry points: [`challenges/index.html`](https://github.com/uihp-challenges/uihp-challenges-april23/blob/main/challenges/index.html) (Index page), [`challenges/part5.js`](https://github.com/uihp-challenges/uihp-challenges-april23/blob/main/challenges/part5.js) (Part 5), [`challenges/part1.js`](https://github.com/uihp-challenges/uihp-challenges-april23/blob/main/challenges/part1.js) (Part 1), [`challenges/part2.js`](https://github.com/uihp-challenges/uihp-challenges-april23/blob/main/challenges/part2.js) (Part 2)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_platform["Browser platform"]
  node_browser(("Browser<br/>runtime boundary"))
  node_dom["DOM<br/>document tree"]
  node_cssom["CSSOM<br/>style tree"]
  node_jsruntime["JS runtime<br/>script runtime"]
  node_events(("Events<br/>input flow"))
  node_timers(("Timers<br/>async loop"))
end

subgraph group_shell["Static shell"]
  node_html["Index page<br/>html entrypoint<br/>[index.html]"]
  node_css["Stylesheet<br/>presentation layer<br/>[styles.css]"]
end

subgraph group_lessons["Lesson parts"]
  node_part1["Part 1<br/>imperative DOM<br/>[part1.js]"]
  node_part2["Part 2<br/>state-to-view<br/>[part2.js]"]
  node_part3["Part 3<br/>virtual DOM<br/>[part3.js]"]
  node_part4["Part 4<br/>list render<br/>[part4.js]"]
  node_part5["Part 5<br/>store + diff<br/>[part5.js]"]
  node_data[("State store<br/>shared data")]
  node_vdom["Virtual DOM<br/>ui description"]
  node_diff{{"Diff engine<br/>reconciliation"}}
  node_render["Render step<br/>dom update"]
end

node_browser -->|"loads"| node_html
node_browser -->|"applies"| node_cssom
node_html -->|"switches to"| node_part1
node_html -->|"switches to"| node_part2
node_html -->|"switches to"| node_part3
node_html -->|"switches to"| node_part4
node_html -->|"switches to"| node_part5
node_css -->|"drives"| node_cssom
node_part1 -->|"mutates"| node_dom
node_part1 -->|"listens"| node_events
node_events -->|"triggers"| node_part1
node_part2 -->|"updates"| node_data
node_part2 -->|"projects"| node_render
node_timers -->|"refreshes"| node_part2
node_part3 -->|"describes"| node_vdom
node_vdom -->|"converts"| node_render
node_render -->|"replaces"| node_dom
node_part4 -->|"maps"| node_vdom
node_part4 -->|"appends"| node_render
node_part5 -->|"stores"| node_data
node_part5 -->|"compares"| node_diff
node_diff -->|"limits"| node_render
node_part5 -->|"triggers"| node_render
node_jsruntime -->|"executes"| node_part1
node_jsruntime -->|"executes"| node_part2
node_jsruntime -->|"executes"| node_part3
node_jsruntime -->|"executes"| node_part4
node_jsruntime -->|"executes"| node_part5
node_browser -->|"dispatches"| node_events
node_browser -->|"schedules"| node_timers

click node_html "https://github.com/uihp-challenges/uihp-challenges-april23/blob/main/challenges/index.html"
click node_css "https://github.com/uihp-challenges/uihp-challenges-april23/blob/main/challenges/styles.css"
click node_part1 "https://github.com/uihp-challenges/uihp-challenges-april23/blob/main/challenges/part1.js"
click node_part2 "https://github.com/uihp-challenges/uihp-challenges-april23/blob/main/challenges/part2.js"
click node_part3 "https://github.com/uihp-challenges/uihp-challenges-april23/blob/main/challenges/part3.js"
click node_part4 "https://github.com/uihp-challenges/uihp-challenges-april23/blob/main/challenges/part4.js"
click node_part5 "https://github.com/uihp-challenges/uihp-challenges-april23/blob/main/challenges/part5.js"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_browser,node_dom,node_cssom,node_jsruntime,node_events,node_timers toneBlue
class node_html,node_css toneAmber
class node_part1,node_part2,node_part3,node_part4,node_part5,node_data,node_vdom,node_diff,node_render toneMint
```

## Components

### Browser platform

Standard browser runtime and rendering boundaries.

- **Browser**: runtime boundary · The execution environment that provides DOM, events, timers, and rendering.
- **DOM**: document tree · Live document tree mutated or regenerated by the lesson scripts.
- **CSSOM**: style tree · Style model used by the browser to render the page.
- **JS runtime**: script runtime · Browser JavaScript environment with access to document, properties, and timers.
- **Events**: input flow · User input and DOM events that trigger updates.
- **Timers**: async loop · Timer-driven refresh used in the state-to-view lesson.

### Static shell

Single HTML entrypoint and stylesheet for the lesson page.

- [Index page](https://github.com/uihp-challenges/uihp-challenges-april23/blob/main/challenges/index.html): html entrypoint · Single browser entrypoint that loads one lesson script at a time. · `challenges/index.html`
- [Stylesheet](https://github.com/uihp-challenges/uihp-challenges-april23/blob/main/challenges/styles.css): presentation layer · Static CSS that affects rendering but not behavior. · `challenges/styles.css`

### Lesson parts

Alternative JavaScript entrypoints showing progressively richer UI architecture.

- [Part 1](https://github.com/uihp-challenges/uihp-challenges-april23/blob/main/challenges/part1.js): imperative DOM · Queries existing nodes, stores references, and mutates text content directly. · `challenges/part1.js`
- [Part 2](https://github.com/uihp-challenges/uihp-challenges-april23/blob/main/challenges/part2.js): state-to-view · Separates data from view and copies state into the DOM through one-way binding. · `challenges/part2.js`
- [Part 3](https://github.com/uihp-challenges/uihp-challenges-april23/blob/main/challenges/part3.js): virtual DOM · Builds UI from element descriptions and converts them into real DOM nodes. · `challenges/part3.js`
- [Part 4](https://github.com/uihp-challenges/uihp-challenges-april23/blob/main/challenges/part4.js): list render · Maps a variable-length virtual DOM list into rendered elements and replaces the body content. · `challenges/part4.js`
- [Part 5](https://github.com/uihp-challenges/uihp-challenges-april23/blob/main/challenges/part5.js): store + diff · Uses a shared data store, centralized updates, and diff-based reconciliation. · `challenges/part5.js`
- **State store**: shared data · Single source of truth for lesson data in the final part.
- **Virtual DOM**: ui description · Structured view description used to generate or reconcile real DOM.
- **Diff engine**: reconciliation · Compares previous and current virtual trees to find minimal changes.
- **Render step**: dom update · Converts view descriptions into DOM updates or replacements.

## Connections

- Browser → Index page: loads · The browser loads the single HTML entrypoint.
- Browser → CSSOM: applies · The browser parses the stylesheet into the style model.
- Index page → Part 1: switches to · The HTML page can point its script tag at the first lesson entrypoint.
- Index page → Part 2: switches to · The HTML page can point its script tag at the second lesson entrypoint.
- Index page → Part 3: switches to · The HTML page can point its script tag at the third lesson entrypoint.
- Index page → Part 4: switches to · The HTML page can point its script tag at the fourth lesson entrypoint.
- Index page → Part 5: switches to · The HTML page can point its script tag at the fifth lesson entrypoint.
- Stylesheet → CSSOM: drives · Stylesheet rules shape how the browser renders the page.
- Part 1 → DOM: mutates · Directly updates existing DOM nodes.
- Part 1 → Events: listens · Uses input events to react to user changes.
- Events → Part 1: triggers · User input calls the handler that mutates the DOM.
- Part 2 → State store: updates · Event handlers update state rather than directly editing the view.
- Part 2 → Render step: projects · State is copied into DOM properties through a view function.
- Timers → Part 2: refreshes · Periodic updates can force repeated view synchronization.
- Part 3 → Virtual DOM: describes · The UI is represented as structured metadata.
- Virtual DOM → Render step: converts · Virtual descriptions are turned into real DOM nodes.
- Render step → DOM: replaces · The rendered DOM is regenerated as a whole.
- Part 4 → Virtual DOM: maps · Processes an arbitrarily sized list of view descriptions.
- Part 4 → Render step: appends · Renders the mapped list into the document body.
- Part 5 → State store: stores · Uses one shared object as the state source.
- Part 5 → Diff engine: compares · Compares previous and current virtual trees.
- Diff engine → Render step: limits · Only changed nodes are reconciled to the DOM.
- Part 5 → Render step: triggers · State updates automatically invoke DOM refresh.
- JS runtime → Part 1: executes · Browser JavaScript runs the lesson scripts.
- JS runtime → Part 2: executes · Browser JavaScript runs the lesson scripts.
- JS runtime → Part 3: executes · Browser JavaScript runs the lesson scripts.
- JS runtime → Part 4: executes · Browser JavaScript runs the lesson scripts.
- JS runtime → Part 5: executes · Browser JavaScript runs the lesson scripts.
- Browser → Events: dispatches · The browser delivers user interaction events.
- Browser → Timers: schedules · The browser provides timer callbacks.
