Frontmatter

Generating PHP templates from a static HTML design

How to convert a static HTML/CSS design into clean PHP include-based templates - variable contracts, conditional rendering, and how to automate the conversion without rewriting your structure.

Converting static HTML into PHP templates is a translation problem. The structure already exists; the goal is to make it reusable without rewriting the design.

The conversion problem

A static HTML design has hard-coded values everywhere. Titles, paths, button labels, repeated cards - all of it lives directly in the markup.

To make it reusable, you need to identify what is dynamic, decide what each value should be called, and then split the structure into partials and page templates. Doing that by hand is slow, repetitive, and easy to get wrong.

PHP template anatomy

A good generated PHP partial follows the same pattern every time:

  • One file per component in partials/
  • Variables read from $fm['props']
  • htmlspecialchars() for output escaping
  • if (!empty(...)) for optional fields
  • include for composition

Example:

<section class="hero">
  <h1>Welcome</h1>
  <p>We build things that last.</p>
</section>

Becomes:

<?php // partials/hero.php ?>
<section class="hero">
  <h1><?= htmlspecialchars($fm['props']['headline']) ?></h1>
  <?php if (!empty($fm['props']['sub'])): ?>
    <p><?= htmlspecialchars($fm['props']['sub']) ?></p>
  <?php endif; ?>
</section>

The HTML structure stays identical. Only the static values become variables.

The variable contract

The reason generated templates stay maintainable is that the expected variables are documented. An INTEGRATION.md file should tell the backend developer:

  • which template expects which variables
  • which values are required
  • which values are optional
  • what shape arrays and nested data should have

That contract is what keeps the PHP side explicit.

Why Astro as the structured intermediate

Without a structured intermediate, HTML-to-PHP conversion is manual and inconsistent. A constrained Astro project gives the converter a typed source of truth: Props interfaces, explicit slots, and a stable component tree.

Frontmatter Solo reads that structure and generates the PHP partials automatically, with $fm['props'] as the namespace for component data.

That approach works for WordPress, Laravel Blade with includes, Symfony without Twig, or any custom PHP backend.

Running Solo for PHP output

frontmatter solo:build --adapter php

The same Astro project can also produce Twig output with --adapter twig if the backend needs it. Use Frontmatter Solo when you want the render pack generated in one pass.