WordPress writes it. Astro builds it.
“Headless” means WordPress only stores and edits the content. It doesn’t make the pages anymore. Astro takes over that job, once, at build time, and the finished HTML is served from a CDN.
From “Publish” to a live page
Edit in WordPress
Projects are a custom post type with plain fields: title, summary, platforms, tags, live URL and a screenshot.
REST API
WordPress serves the content as JSON at
/wp-json/wp/v2/projects, with the image and platform names ready to use.Astro build
Astro fetches that JSON once and writes a static HTML page for every project. No JavaScript framework ships to the browser.
CDN + rebuild hook
The files go to Cloudflare Pages. When I publish in WordPress, a deploy hook rebuilds the site automatically.
The whole data layer is one fetch
Every page gets its content from a single function. It runs at build time on the server, so visitors never wait for an API call, and WordPress could even go offline without taking this site down.
The filters on the Work page don’t use JavaScript either. They’re radio buttons and the CSS:has() selector.
// src/lib/wp.ts (simplified)
const API = "https://hjmiranda.com/wp-json/wp/v2";
export async function getProjects() {
const res = await fetch(
`${API}/projects?per_page=100&orderby=menu_order`
);
const raw = await res.json();
return raw.map(toProject);
}
// src/pages/work/[slug].astro
export async function getStaticPaths() {
const projects = await getProjects();
return projects.map((project) => ({
params: { slug: project.slug },
props: { project },
}));
}WordPress vs. Astro, same content
Both score 100 after tuning, so the difference shows in the details: Astro paints sooner and ships a fraction of the HTML and CSS, with no JavaScript at all.
| Metric | WordPress + Elementor | Astro (headless) |
|---|---|---|
| Mobile PageSpeed score | 100 | 100 |
| First Contentful Paint | 1.0 s | 0.8 s |
| Largest Contentful Paint | 1.0 s | 0.8 s |
| Speed Index | 2.4 s | 0.8 s |
| Total Blocking Time | 0 ms | 0 ms |
| HTML size | 83 KB | 29 KB |
| CSS on first load | 135 KB (combined by LiteSpeed) | 13 KB (inlined) |
| JavaScript on first load | 17 KB loader; the rest is delayed until the visitor interacts | 0 KB |
| Hosting | PHP hosting + database (Hostinger) | Free static hosting (Cloudflare Pages) |
| Changing a project | Edit in Elementor, publish | Edit fields in WordPress, publish, rebuilds in about a minute |
When I’d pick each one
WordPress + Elementor is still the right call when a client’s team needs to design and rearrange pages themselves, or needs plugins like WooCommerce, memberships or forms with no extra setup.
Headless with Astro fits content-heavy marketing sites, docs and portfolios where speed and security matter most, and where layouts are set once by a developer while editors only change content.
This build: 14 projects from WordPress · last built Nov 13, 2026, 5:15 PM GMT+8.