pw-url-routing
Use when utilizing ProcessWire URL/Path hooks to create custom routing, virtual pages, or API endpoints without physical backend templates.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when utilizing ProcessWire URL/Path hooks to create custom routing, virtual pages, or API endpoints without physical backend templates.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
Use when building, structuring, or refactoring native backend modules for ProcessWire using PHP 8.4 and strict typing.
Use when designing, structuring, or rendering HTML for ProcessWire Admin interfaces, custom Process modules, or Inputfields.
Use when brainstorming or designing ProcessWire modules, templates, field schemas, or hooks to resolve ambiguity and validate architecture before implementation.
Use when creating, executing, or managing Pest tests within ProcessWire or ProcessWire modules, including Test-Driven Development (TDD) tasks.
Use when encountering any bug, test failure, blank screen of death, or unexpected behavior in ProcessWire before proposing fixes.
Use when creating or updating module documentation, package READMEs, architecture guides, or CLI command references for ProcessWire projects.
| name | pw-url-routing |
| description | Use when utilizing ProcessWire URL/Path hooks to create custom routing, virtual pages, or API endpoints without physical backend templates. |
| risk | safe |
| source | processwire-boost |
| date_added | 2026-04-08 |
Use this skill when you need to:
[!IMPORTANT] CRITICAL DOCUMENTATION RULE: Before writing any ProcessWire code or using its API, you MUST consult the local API documentation located at
.agents/docs/index.md. You MUST NOT hallucinate API methods. ALL code, documentation, and file contents MUST strictly be written in English. Ensure inner code strings are always in English and wrapped in ProcessWire translation functions ($this->_('English String')or__('English String', __FILE__)) so they can localized if needed.
URL hooks are defined during the ProcessWire boot process, typically in site/init.php (recommended) or site/ready.php, or inside a module's init() method.
To output a string directly:
$wire->addHook('/api/hello', function($event) {
return 'Hello World';
});
To output HTML and prevent further ProcessWire output, return true:
$wire->addHook('/api/hello', function($event) {
echo '<h1>Hello World</h1>';
return true;
});
You can return a Page object to map a custom URL directly to an existing page. ProcessWire will make this the active $page and render it normally:
$wire->addHook('/special-offer', function($event) {
return $event->pages->get('/about/contact/');
});
You can extract values from the URL into arguments.
{argument_name}$wire->addHook('/hello/{planet}', function($event) {
// You can access it via arguments or directly
$planet = $event->arguments('planet');
// or $event->planet;
// Validate or return false for a 404 response
if (!in_array($planet, ['earth', 'mars'])) {
return false;
}
return "Hello " . $planet;
});
(name:pattern)$wire->addHook('/hello/(planet:earth|mars|jupiter)', function($event) {
return "Hello " . $event->planet;
});
If the path structure is complex, you can use full PCRE regex patterns.
Remembering portions of the matched URL without named arguments uses $event->arguments(1).
$wire->addHook('(/.*)/json', function($event) {
$path = $event->arguments(1);
$page = $event->pages->findOne($path);
if (!$page->id || !$page->viewable()) {
return false;
}
// Returning an array automatically outputs as JSON with proper Content-Type
return [
'id' => $page->id,
'title' => $page->title
];
});
[!WARNING] Trailing Slashes: ProcessWire strictly enforces trailing slashes.
/foo/bar/definition will 301 redirect/foo/barto/foo/bar/. To accept both without redirecting:$wire->addHook('/foo/bar/?', ...)
[!NOTE] Pagination: URL hooks ignore numbered pagination by default (
/foo/bar/page2). To support pagination, append{pageNum}strictly as the last segment without a trailing slash:$wire->addHook('/foo/bar/{pageNum}', ...)The page number can be accessed via$event->pageNum.
application/json header.$page.true: Tells ProcessWire you output the data manually (via echo).false or null: Instructs ProcessWire to return a standard 404 response.Instead of checking request types inside the hook callback, conditionally wrap the hook registration to save memory and process cycles:
if ($input->is('POST')) {
$wire->addHook('/api/submit', function($event) { /* Handle POST */ });
}