9. Addressable bodies and projection

Attach renderable content to your own typed data records and render it elsewhere with project — the wskill mechanism.

After this lesson you can

- Declare a custom @block type with a @child("body") content slot - Gather instances with a merging @document - Render each record's body by reference with project

Before you start: Components and repeaters

A body attaches a chunk of renderable content to a data record as a property — the record itself is not a renderable block. Declare your own @block type with a @child("body") … : WdocAddressableBody? slot, plus a merging @document so the document gathers the instances into a list your pages can repeat over.

A project { from = record.body } then renders *that* record's fragment wherever the projection needs it; ${…} inside the body resolves against the record. A body never renders where it is declared, only where projected. This body/project pattern is exactly how a wskill's book projects its concept and fact pages.

§ 1Exercise: A projected fleet page

Declare a server block carrying a body, author two servers, and project each body onto a fleet page.

wcl
import <wdoc.wcl>

@block("server")
type Server {
  @inline(0) name: identifier
  region: utf8?
  @child("body") overview: WdocAddressableBody?
}

@document
type FleetDoc {
  @children("server") servers: list<Server>
}

server web01 { region = "us-east"
  body { p $"Frontend in ${region}." }
}

server web02 { region = "eu-west"
  body { p $"Frontend in ${region}." }
}

page fleet { start = true
  h1 "Fleet"
  wdoc_repeater { each = servers  as = :s
    h2 $"${s.name}"
    project { from = s.overview }
  }
}

Expected result

The fleet page shows an h2 per server followed by its projected body — each paragraph naming its own region.

Hint

Your own @document merges with wdoc's, so page blocks stay legal alongside server. The single @child("body") slot means the body needs no name.