Custom projections (schema extension modules)
Generated Markdown for references/concept_custom_projection.md.
Open book page Back to the skill graph
# Custom projections (schema extension modules)
_Model domain data — a language's builtins, a CLI surface — as typed blocks in a schema module, then project them into generated reference pages._
When a topic has recurring domain data the four unit kinds don't capture — the builtin
functions of a language, the subcommand tree of a CLI, a keybinding table — model it as
its OWN schema and project it, instead of flattening it into prose facts. The pattern is
a \*schema extension module\*: a `.wcl` file declaring typed `@block`s plus a merging
`@document` that gathers them.
```wcl
// schema/keybindings.wcl — a topic-specific extension module
namespace wcl.wskill
@block("keybinding")
type Keybinding {
@inline(0) id: identifier
keys: utf8
action: utf8
context: utf8?
}
// Merges with the base @document — `keybindings` gathers only where imported.
@document
type KeybindingDoc {
@children("keybinding") keybindings: list<Keybinding>
}
```
Import the module from `wskill.wcl`, author instances in `data/`, then add a render to
each projection template — typically a `wdoc_repeater` generating one page (or one table
row) per instance. Because imported `@document` schemas MERGE with the base, the
extension composes cleanly with everything else.
The wcl wskill is the worked example at scale: its `schema/builtins.wcl` and
`schema/cli.wcl` modules capture 80+ builtin functions and the whole `wcl` subcommand
tree as data, projected into generated per-function and per-command reference pages.
Two standard modules ship with every wskill — the [presentation](../references/concept_presentation_view.md)
and [training](../references/concept_training_view.md) views use exactly this mechanism.
## Examples
### A typed custom block
Declare an @block plus a @document that gathers it; imported documents merge with the base. Then add a render to both template sets.
```wcl
@block("keybinding")
type Keybinding {
@inline(0) id: identifier
keys: utf8
action: utf8
context: utf8?
}
@document
type Extensions {
@children("keybinding") keybindings: list<Keybinding>
}
```
## Related
- [Structured data](../references/concept_structured_data.md)
- [Components: one look for every unit](../references/concept_components_look_feel.md)
- [Creating a schema extension](../references/process_creating_schema_extension.md)
[← Back to SKILL.md](../SKILL.md)