Hook Scoping
Hook scoping controls what subset of site data and pages a hook receives. By declaring what your hook needs at registration time, you reduce the serialization cost of each hook dispatch – especially important for large sites with thousands of pages.
The scope: Options
data – Site Data Keys
Controls which site.data keys are serialized in the hook payload.
| Value | Behavior |
|---|---|
undefined (omitted) |
No site data serialized |
["navigation", "team"] |
Only these keys |
["*"] |
All site data keys |
pages – Page Filtering
Controls which pages are included in the hook payload.
| Value | Mode | Description |
|---|---|---|
false (default) |
Skip | No pages serialized |
true or "**" |
All | All pages included |
"/blog/**" |
Glob | Only pages matching the path glob |
{ tags: ["component"] } |
Taxonomy | Only pages matching taxonomy terms |
Taxonomy Filter Rules
Multiple terms within the same taxonomy are OR’d (union):
Multiple taxonomies are AND’d (intersection):
pageFields – Per-Page Fields
Controls which fields are populated on each page in the payload.
| Value | Behavior |
|---|---|
undefined (omitted) |
All fields |
["frontMatter", "url"] |
Only these fields |
["*"] |
All fields (explicit) |
Available fields: path, url, frontMatter, content, html, toc.
Union Scope
When multiple hooks register for the same event with different scopes, Alloy computes a union and serializes it once for all hooks on that event.
If hook A requests pageFields: ["html"] and hook B requests pageFields: ["toc"], both hooks receive pages with html AND toc populated.
This is a performance optimization – one serialization pass per event instead of one per hook. Scoping reduces the total work, but it is not an isolation boundary. Plugin A may see fields it did not request if another plugin on the same event requested them.
addPages Return Shape
When a hook declares pages: false and needs to inject virtual pages (via onPagesReady), use the addPages return shape to avoid round-tripping all existing pages:
The pipeline detects the addPages key and appends the new pages without requiring the plugin to process existing pages.
Virtual pages can declare dependencies to optimize incremental rebuilds — see Virtual page dependencies.
Hook Availability Matrix
Not all scope options work on all hooks. Two constraints apply:
-
Pageless hooks (
onConfig,onBeforeValidation,onAfterValidation,onDataFetched) do not receive pages. Settingpagesto anything other thanfalseproduces a validation error. -
Pre-taxonomy hooks (
onPagesReady) cannot use taxonomy filtering because taxonomy indices have not been built yet.
| Hook | Pages | Glob Filter | Taxonomy Filter |
|---|---|---|---|
onConfig |
no | error | error |
onBeforeValidation |
no | error | error |
onAfterValidation |
no | error | error |
onDataFetched |
no | error | error |
onPagesReady |
yes (batch) | accepted* | error |
onContentLoaded |
yes (batch) | yes | yes |
onDataCascadeReady |
yes (batch) | yes | yes |
onContentTransformed |
per-page | n/a | n/a |
onPageRendered |
per-page | n/a | n/a |
onAssetProcess |
per-asset | n/a | n/a |
onBuildComplete |
no | n/a | n/a |
* onPagesReady accepts a glob in the pages option without error, but the payload always includes all pages regardless. Glob filtering is not applied for this hook — use pages: true or pages: false instead.
Per-page hooks (onContentTransformed, onPageRendered) fire with a fixed payload shape. The pipeline already knows which page to serialize, so pages and pageFields scope options do not apply. Use data and priority on per-page hooks.
Registering an invalid scope mode on a hook produces a validation error at plugin load time – before the build starts.
Practical Example: Docs Site with Component Demos
A documentation site that generates demo pages from a data file, only processing pages it cares about:
Related
- Lifecycle Events – all hook events and payloads
- Plugin System – plugin tiers and registration