Including sub-sites
The include block builds *other* wdoc documents found under a folder and ships each one's rendered output into a subdirectory of this build — exactly as if you had run wcl wdoc build (or wcl wdoc skill) on each one separately. Unlike imports, which merge another file's blocks into the current document, an included document stays a separate artifact: it keeps its own pages and _wdoc/ assets under its own output subdirectory.
Include vs import
import pulls another file's declarations into *this* document (one merged site). include builds another document on its own and copies the result in (many independent sites under one output tree).
§ 1Discovery: pattern vs entry
Name a folder (the inline label), then pick exactly one discovery mode. Each match builds into <folder-basename>/<name>/.
pattern — a filename glob (* / ?) matched *recursively* against every file in the folder's subdirectories. The sub-site name is the matching file's parent folder, relative to the scanned folder. Good for a flat folder of single-file sites.
import <wdoc.wcl>
// projects/foo/main.wcl → <out>/projects/foo/
// projects/bar/main.wcl → <out>/projects/bar/
// projects/shared.wcl → ignored (not inside a subdirectory)
include "projects" { pattern = "main.wcl" }
entry — a fixed relative path checked inside each *immediate* subdirectory of the folder (no recursion). Each subdirectory that has the entry file is one sub-site named after that subdirectory. Rendered out/ trees, _wdoc/, and bundled subtrees are never scanned, and the entry may sit at a fixed deep path — ideal for a folder of whole projects.
// members/ls/wdoc/book/main.wcl → <out>/members/ls/
// members/cat/wdoc/book/main.wcl → <out>/members/cat/
// members/ls/out/** → never scanned
include "members" { entry = "wdoc/book/main.wcl" }
§ 2Picking a site
A member may declare several sites (e.g. a :book web site and an :ai_skill site over one model). The optional site field names which one to build — it is passed as --site to the per-member build:
include "members" { entry = "main.wcl" site = "book" } // each member's :book site only
The companion included_sites(options) builtin runs the same scan and returns one { name, href, title, summary } record per discovered sub-site — name is the sub-site folder, href its root-relative URL, and title / summary come from the member's selected site (title falling back to name). The argument is a record mirroring the include block's fields (WCL has no keyword arguments); pass the *same* options so the links line up with where the sub-sites were built. Note record fields use : where block fields use =.
site main { root = true default_template = :webpage
menu {
item "Home" { page = index }
wdoc_repeater { each = included_sites({ folder: "members", entry: "main.wcl", site: "book" }) as = :s
item $"" { href = s.href } // label from the member's title
}
}
}
Multi-site hrefs
included_sites returns root-relative hrefs (members/foo/). A non-root site renders under /<site>/, so its menu must reach a sibling sub-site with a ../ prefix (../members/foo/).
§ 4Skill collections
Because include also embeds for the skill target, one wcl wdoc skill renders every member's skill into <out>/<folder>/<name>/ (each a SKILL.md + references/). A collection document can be pure fan-out — just include blocks, no site of its own:
import <wdoc.wcl>
include "../members" { entry = "main.wcl" site = "skill" } // each member's :skill site
§ 5Notes
- Sub-sites are embedded by the HTML build (wcl wdoc build), the dev server, and the skill target (wcl wdoc skill). The Markdown and PDF targets define included_sites so documents still parse, but do not embed sub-sites.
- Set exactly one of pattern or entry; an include with neither (or both) is a build error.
- Add a summary = "…" to a member's site block to surface a one-line description through included_sites (it isn't rendered by the built-in templates).
- An include chain that references one of its own ancestors is rejected as a cycle rather than looping.