EN | ES

Template System

Wordless uses pure PHP for templating, with no external templating engine. This means zero learning curve and full access to PHP's power when needed.

Why Pure PHP?

Pure PHP templates offer several advantages:

  • No abstraction overhead: Write HTML and PHP directly
  • Full language features: Use any PHP function without restrictions
  • Fast performance: No compilation step or template parsing
  • Familiar syntax: Developers already know PHP
  • Zero dependencies: No additional libraries to install

Template Structure

Layouts

Layouts wrap content pages with headers, footers, and navigation:

<!DOCTYPE html>
<html>
<?= $renderer->partial('head', ['pageTitle' => $pageTitle]) ?>
<body>
    <?= $renderer->partial('nav') ?>
    <main>
        <?= $slot ?>
    </main>
    <?= $renderer->partial('footer') ?>
</body>
</html>

Partials

Reusable components are stored as partials in templates/partials/:

templates/partials/
  head.php      → <head> with meta tags and CSS
  nav.php       → Navigation menu
  footer.php    → Site footer

Content Pages

Content files under content/ declare $meta and output HTML directly. The layout is applied by templates/page.php:

<!-- content/en/about.php -->
<?php $meta = [
    'title'       => 'About',
    'description' => 'About Wordless CMS.',
    'keywords'    => ['wordless', 'about'],
]; ?>

<h1>About Wordless</h1>
<p>Content goes here — plain PHP and HTML.</p>

The renderer wraps this in templates/page.php, which sets the layout and passes $content->body into templates/layouts/base.php.

Output Escaping

Always use the e() helper to escape user-controlled output:

<!-- Safe -->
<h1><?= e($title) ?></h1>

<!-- Unsafe -->
<h1><?= $title ?></h1>

The e() function uses htmlspecialchars() with strict flags to prevent XSS attacks.

Rendering Process

When a page is requested:

  1. Content is loaded from the filesystem
  2. The page template renders the content
  3. If the template declares $layout, it's wrapped in that layout
  4. The final HTML is returned to the client

Accessing Data

Templates receive data via variable injection:

// In your renderer
$renderer->render('page', [
    'content' => $contentObject,
    'related' => $relatedPages,
]);

// In the template
<?php
$content->title;    // Available as $content
$related;           // Available as $related
$renderer;          // Always available
?>

Best Practices

  • Always escape output: Use e() for all user-controlled data
  • Keep logic minimal: Use templates for presentation, not business logic
  • Use semantic HTML: Structure for accessibility and SEO
  • Reuse partials: Create reusable components for common patterns
  • Separate concerns: Keep template markup away from PHP logic when possible

← Back to Features