Wanderland

Wanderland Lantern Pack

A server-rendering pack for wanderland-core engines. It turns a YAML layout plus resolved data into an HTML page: layouts are trees of components, each component is a server-side painter that emits HTML (the grin), and a browser enhances the result on the client (the cat). This is the Ruby realization of the lantern-component-framework design for wanderland-core.

The gem lives at wanderland-lantern-pack and mirrors the structure of wanderland-aws-pack: a gemspec, an entry file that requires the library, and boundaries that self-register on load.

Install

In an engine's Gemfile:

gem "wanderland-lantern-pack"

Require it before Wanderland.boot (the wanderland binary's Bundler.require(:default) does this automatically):

require "wanderland-core"
require "wanderland-lantern-pack"

Loading the pack registers the lantern_html formatter (serves: "text/html") and the built-in component painters.

The render model

A page is { layout, data, title }. The lantern_html formatter receives this as the principal result and composes it into a full HTML page.

A layout is a tree. A node is either a container or a component:

type: vlayout            # or hlayout — stacks its children
children:
  - component: header
    bind: header         # dotted path selecting the data slice this component paints
  - component: kv-table
    args: { title: metadata }   # literal props
    bind: meta
  - component: link-list
    args: { title: "Depends on" }
    bind: out

bind selects a slice of data by dotted path (header, meta, node.attrs); args are literal properties. The renderer passes each painter a props hash: the literal args plus data (the bound slice).

Built-in components

Domain-agnostic painters. An engine binds its own data into these, or registers its own painters alongside them.

Component data shape it paints
header { kind, title, tags: [..] } — an identity header
kv-table a flat { key: value } hash — a metadata table (args.title)
link-list [{ label, href, note }] — a list of links (args.title)
markdown a markdown string — rendered body (args.title)
raw an HTML string — passthrough

Adding components

A component is a painter registered by name. props["data"] is the bound slice; the rest are literal layout args.

Wanderland::Lantern.register("badge") do |props|
  d = props["data"] || {}
  %(<span class="badge #{Wanderland::Lantern.h(d["status"])}">#{Wanderland::Lantern.h(d["label"])}</span>)
end

Wanderland::Lantern.h is the shared HTML-escape helper. All meaning belongs in the painted HTML — a web component's enhance() grants liveness, never content.

The page frame and data carrier

Wanderland::Lantern::Page.frame(title, body, data) wraps a composed body in the HTML shell with the stylesheet and a data carrier: a <script type="application/json"> holding the resolved data. A machine reads a complete, addressable, JavaScript-free page; a browser enhances from the same carrier. The body never depends on JavaScript to mean something.

The formatter

boundary :lantern_html, serves: "text/html"

It renders a { layout, data, title } principal into a page, and falls back to a framed JSON dump for any other shape. Because formatter registration is keyed by MIME and last-write-wins, an engine that loads this pack serves text/html through lantern_html. Boot loads core boundaries (including the core html_formatter) after gems are required, so an engine pins the formatter from a boundary_path file — which loads after core during boot — with Wanderland::Formatters.register("text/html", :lantern_html).

Library structure

lib/wanderland-lantern-pack.rb                       entry — requires the library + formatter
lib/wanderland/lantern.rb                            component registry + h() escape
lib/wanderland/lantern/renderer.rb                   compose(layout, data) → HTML; render_page
lib/wanderland/lantern/components.rb                 built-in painters
lib/wanderland/lantern/page.rb                       Page.frame — shell, CSS, data carrier
lib/wanderland/lantern/boundaries/lantern_html.rb    the text/html formatter

First consumer

Dark Lantern renders graph nodes through the pack. Its graph_page boundary pulls a node and its edges from the dependency graph, shapes them for header / kv-table / link-list, loads the page layout from resources/layouts/node.yml, and returns { layout, data, title }. The route GET /node/*path serves a node page; each edge renders as a link to the other node's page, so the graph is walkable by clicking. See dark-lantern.

Status

Implemented: the render model, the five built-in components, the page frame and data carrier, and the text/html formatter. The lantern-component-framework design names a wider vocabulary — modeline projections (row / card / bar / panel), record-list, filter-bar, oculus-button, and a layout-resource page chain (yaml_loader → data_fetch → variable_resolve → layout_compose → frame_assemble). Those land as the component set grows. Markdown rendering with fence execution arrives by mixing in the loom pack.