When a static design needs to become a WordPress theme, the work is mostly mechanical. The layout already exists. The job is to translate it into PHP files and wire in data without breaking the structure.
The traditional approach - and why it breaks down
The usual workflow is to split index.html into header.php, footer.php, and index.php, then replace static strings with WordPress template tags by hand.
That works for tiny sites. It breaks down as soon as the design gets more complex. Variables get named differently from page to page, optional blocks get missed, and the backend developer has to reverse-engineer what the theme expects.
What a WordPress PHP theme needs
The minimum files are predictable:
style.css- theme declaration header plus your CSSindex.php- the main fallback templateheader.php/footer.php- shared structurepage-{slug}.php- per-page templatespartials/- reusable includes
Solo generates the rendering layer. Your WordPress developer wires the data.
| Generated by Solo | Written by your WordPress developer |
|---|---|
PHP partials (partials/hero.php, etc.) | functions.php |
Layout (layouts/base.php) | WordPress hooks and filters |
| Page template stubs | get_field() / WP_Query calls |
manifest.json | Menu registration |
INTEGRATION.md | Plugin integration (ACF, Yoast, etc.) |
The variable contract - $fm
The generated templates use a simple contract:
$fm['props']- template-specific values$fm['site']- global site data$fm['page']- page-level metadata$fm['data']- loops and shared collections
That contract is what lets the partials stay clean. The partial renders what it receives. It does not fetch its own data.
<?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>
Why structure your design in Astro first
Static HTML has no typed props and no enforced contract. Astro gives you both. A constrained Astro project tells you exactly which fields are required, which are optional, and how the structure is composed before the conversion starts.
That makes the PHP output predictable. It also makes the integration doc useful, because the backend developer is wiring a contract instead of guessing at intent.
Run solo-check first if you want to validate the project before you generate the PHP output.
Running Solo
frontmatter solo:build --adapter php
Use Frontmatter Solo when you want the generated WordPress render pack - partials, layouts, page templates, manifest, and INTEGRATION.md - without rewriting the frontend by hand.