.claude/skills/klytos-custom-templates/SKILL.md
Guide for creating custom page templates, template parts, hook points, reusable blocks, and page template recipes in Klytos CMS. Use when creating new page layout templates, customizing template parts, adding frontend hook points, defining reusable blocks with slots, or building page template recipes combining multiple blocks.
npx skillsauth add joseconti/klytos Klytos Custom TemplatesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this reference when you need to create new page layout templates, customize template parts, add frontend hook points, define reusable HTML blocks with configurable slots, or build page template recipes that combine multiple blocks.
| System | Purpose | Stored In |
|---|---|---|
| TemplateResolver | 4-level template resolution hierarchy | core/template-resolver.php |
| Template Parts | Shared fragments (header, footer, head, scripts) | templates/parts/ + custom-templates/parts/ |
| Hook Points | Frontend JS injection points (data-klytos-hook) | core/assets/klytos-hooks-*.js |
| HTML Templates | Page layout structure | templates/ + custom-templates/ |
| Page Template Recipes | Block arrangement for a page type | 'page-templates' collection |
| Reusable Blocks | Configurable HTML components with slots | 'blocks' collection |
When the BuildEngine needs a template, it resolves it through this hierarchy (first match wins):
custom-templates/{name}.html -- User customizations (NEVER overwritten by updates)klytos_register_templates() in plugin init.phptemplates.json.enc -- Created from the admin UI (stored in DB/storage)templates/{name}.html -- Core templates (overwritten on update)For pages with a post_type field, templates are resolved in this order:
single-{post_type}-{slug} (e.g. single-product-camiseta-azul)single-{post_type} (e.g. single-product)default// In plugin init.php
klytos_register_templates('my-plugin', [
'single-product' => [
'file' => __DIR__ . '/templates/single-product.html',
'name' => 'Product Page',
'description' => 'Template for product detail pages',
'post_type' => 'product',
],
'cart' => [
'file' => __DIR__ . '/templates/cart.html',
'name' => 'Shopping Cart',
'description' => 'Cart page template',
'dynamic' => true,
],
]);
Place template files in custom-templates/:
custom-templates/default.html -- Overrides core templates/default.htmlcustom-templates/single-product.html -- Overrides plugin's product templatecustom-templates/my-custom.html -- New custom templateShared HTML fragments included via {{klytos_part:NAME}} syntax. Parts are resolved with the same hierarchy as templates but within parts/ subdirectories.
| Part | File | Content |
|---|---|---|
| head | templates/parts/head.html | Meta tags, CSS, fonts, favicon, plugin CSS link |
| header | templates/parts/header.html | Logo, navigation menu |
| footer | templates/parts/footer.html | Footer HTML |
| scripts | templates/parts/scripts.html | JS, body scripts, hooks JS, plugin body end |
<!DOCTYPE html>
<html lang="{{page_lang}}">
<head>
{{klytos_part:head}}
</head>
<body>
{{klytos_part:header}}
<main class="klytos-main">
<div class="klytos-container">
{{page_content}}
</div>
</main>
{{klytos_part:footer}}
{{klytos_part:scripts}}
</body>
</html>
Place a file at custom-templates/parts/header.html to completely replace the core header.
CRITICAL: The build engine automatically prevents header/footer duplication between custom templates and page templates.
When a custom template includes structural elements (via {{klytos_part:header}}, {{klytos_part:footer}}, {{header_html}}, {{footer_html}}, or hardcoded <header>/<footer> tags), the corresponding blocks are automatically excluded from the page template rendering inside {{page_content}}.
| Custom Template Provides | Blocks Excluded from Page Template |
|---|---|
| {{klytos_part:header}} or <header> | top-bar, header |
| {{klytos_part:footer}} or <footer> | footer |
IMPORTANT: The build engine automatically injects the global top-bar block before the first <header> tag in custom templates.
When a custom template provides its own <header> element, the build engine:
top-bar and header blocks from {{page_content}} (deduplication)..klytos-top-bar markup.top-bar global block HTML before the <header> tag.This means:
top-bar block's global_data..klytos-top-bar element, auto-injection is skipped (no duplication).<header> tag are not affected.Hook: build.inject_top_bar (filter) — Modify or suppress the injected top-bar HTML. Return empty string to disable injection.
Rules for AI assistants:
blank.html relies on them.{{klytos_part:header}} + {{klytos_part:footer}}, the page template's header/footer blocks are automatically skipped.blank.html), all blocks from the page template render normally.klytos_set_global_block_data with block_id: "top-bar".Hooks for plugins:
build.structural_block_mapping (filter) — Customize which template indicators map to which block IDs.build.exclude_structural_blocks (filter) — Override the final exclusion list.build.inject_top_bar (filter) — Modify or suppress auto-injected top-bar HTML.page_template.structure_after_dedup (filter) — Modify structure after deduplication filtering.HTML elements with data-klytos-hook attributes where plugins inject content via JavaScript. This avoids rebuilding thousands of static pages when a plugin is activated/deactivated.
Create plugins/{plugin-id}/assets/js/hooks.js:
// Register a hook for the "after_add_to_cart" hook point
registerHook('after_add_to_cart', function(el, pageData) {
if (pageData.type !== 'product') return;
el.innerHTML = '<div class="share-buttons">Share: ...</div>';
}, 10);
Place CSS files in plugins/{plugin-id}/assets/css/. They are concatenated into assets/css/plugins.css automatically.
| Event | JS/CSS rebuilt | Pages rebuilt |
|---|---|---|
| Plugin activated | YES | NO |
| Plugin deactivated | YES | NO |
| buildAll() called | YES | YES |
| Page edited | NO | Only that page |
Stored configurations that define which blocks appear on a page type and in what order.
$templates = klytos_app()->getPageTemplateManager();
$templates->save([
'type' => 'product-page',
'name' => 'Product Page',
'description' => 'For product detail pages',
'structure' => [
['block_id' => 'hero', 'order' => 1],
['block_id' => 'product-specs', 'order' => 2],
],
'wrapper_html' => '<div class="klytos-page">{{blocks_html}}</div>',
'status' => 'active',
'version' => '1.0.0',
]);
Configurable HTML components with "slots" (editable fields).
[
'id' => string, // Block ID
'name' => string, // Display name
'category' => string, // Category
'version' => string, // Semantic version
'status' => string, // 'active' or 'draft'
'scope' => string, // 'global', 'template', or 'page'
'slots' => array, // Slot definitions
'html' => string, // Template with {{slot_name}} placeholders
'css' => string, // Custom CSS
'js' => string, // Custom JS
'sample_data' => array, // Preview data
]
$blocks = klytos_app()->getBlockManager();
$blocks->save([
'id' => 'pricing-card',
'name' => 'Pricing Card',
'category' => 'interaction',
'scope' => 'page',
'slots' => [...],
'html' => '...',
'css' => '...',
'status' => 'active',
]);
$block = $blocks->get('pricing-card');
$all = $blocks->list('interaction', 'active');
$html = $blocks->render('pricing-card', ['plan_name' => 'Pro', 'price' => 29]);
| Hook | Type | Arguments |
|---|---|---|
| template_part.{name} | filter | ?string $html -- modify a template part |
| build.assets_changed | action | (none) -- triggered on plugin activate/deactivate |
| build.head_html | filter | string $html -- inject into <head> |
| build.body_end_html | filter | string $html -- inject before </body> |
| page.content | filter | string $html, array $page -- modify page content |
| block.before_save | action | array $block |
| block.after_save | action | array $block |
| page_template.before_save | action | array $template |
| page_template.after_save | action | array $template |
klytos_register_templates(string $pluginId, array $templates): void
klytos_register_template_part(string $partName, callable $callback, int $priority = 10): void
installer/
templates/ # CORE — Overwritten on updates
default.html # Uses {{klytos_part:X}} syntax
landing.html
blog-post.html
blank.html
parts/ # Shared fragments
head.html
header.html
footer.html
scripts.html
custom-templates/ # USER — NEVER overwritten
parts/ # Override core parts here
plugins/{plugin-id}/
templates/ # Plugin templates
assets/js/hooks.js # Frontend hook registrations
assets/css/*.css # Plugin CSS (auto-concatenated)
core/
template-resolver.php # 4-level resolution engine
build-engine.php # Build with parts, hooks, post type resolution
The following variables are available in HTML templates:
{{page_content}} <!-- Page HTML content -->
{{page_title}} <!-- Page title -->
{{site_name}} <!-- Site brand name -->
{{page_lang}} <!-- Language code -->
{{page_slug}} <!-- URL slug -->
{{menu_html}} <!-- Navigation menu -->
{{footer_html}} <!-- Footer HTML -->
{{base_path}} <!-- Root path -->
{{site_url}} <!-- Absolute site URL -->
{{breadcrumbs}} <!-- Breadcrumb navigation + JSON-LD -->
{{seo_meta_tags}} <!-- OG, Twitter, JSON-LD -->
{{css_variables}} <!-- :root CSS variables -->
{{google_fonts_html}} <!-- Google Fonts links -->
{{custom_css}} <!-- Page-specific CSS -->
{{custom_js}} <!-- Page-specific JS -->
{{head_scripts}} <!-- Analytics head scripts -->
{{body_scripts}} <!-- Analytics body scripts -->
{{hreflang_tags}} <!-- Multilingual links -->
{{og_image}} <!-- Open Graph image -->
{{plugin_head_html}} <!-- Plugin <head> injections -->
{{plugin_body_end_html}} <!-- Plugin </body> injections -->
{{plugin_css_link}} <!-- Plugin CSS stylesheet link -->
{{icons_css_link}} <!-- Font Awesome icon library (when icons_enabled=true) -->
{{blocks_css_link}} <!-- Block CSS stylesheet link -->
{{hooks_js_script}} <!-- Frontend hooks JS script tag -->
{{klytos_part:NAME}} <!-- Template part inclusion -->
core/template-resolver.phpcore/build-engine.phpcore/page-template-manager.phpcore/block-manager.phptemplates/templates/parts/custom-templates/core/assets/klytos-hooks-prelude.js, core/assets/klytos-hooks-executor.jsFor complete v2.0 block rendering, see the references/v2-block-rendering.md file.
development
Guide for working with dates, times, and timezones in Klytos CMS. Use when formatting dates, converting timezones, scheduling actions with timestamps, displaying local time, working with UTC storage, building timezone selectors, or using any klytos_date/klytos_gmdate/klytos_timezone functions.
tools
Guide for developing and extending the Klytos web terminal. Use when modifying terminal commands, adding terminal commands from plugins, fixing terminal bugs, extending the pseudo-terminal, working with TerminalExecutor class, registering custom permissions, adding custom category labels, or managing terminal UI and security.
development
--- name: klytos-site-builder description: Guide for building a complete website from scratch with Klytos CMS. Use when creating a new site, configuring a site after installation, setting up design/content/SEO/navigation, or when the user pastes the post-install prompt. Covers 9 phases: discovery, design reference, global config, theme, content structure, templates, content creation, additional features, and launch. --- # Klytos Site Builder ## Overview The Site Builder is a conversational AI
development
Use when creating or editing page content in Klytos CMS. Ensures every page has proper SEO structure, HTML semantics, meta tags, structured data, accessibility for maximum search engine visibility. Apply when writing page titles, descriptions, content, headings, images, internal links, JSON-LD schema, or following the SEO checklist before publishing pages.