How it’s built

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.

01 — The pipeline

From “Publish” to a live page

  1. Edit in WordPress

    Projects are a custom post type with plain fields: title, summary, platforms, tags, live URL and a screenshot.

  2. REST API

    WordPress serves the content as JSON at /wp-json/wp/v2/projects, with the image and platform names ready to use.

  3. Astro build

    Astro fetches that JSON once and writes a static HTML page for every project. No JavaScript framework ships to the browser.

  4. CDN + rebuild hook

    The files go to Cloudflare Pages. When I publish in WordPress, a deploy hook rebuilds the site automatically.

02 — The code

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 },
  }));
}
03 — The results

WordPress vs. Astro, same content

Measured with PageSpeed Insights on mobile. Numbers I haven’t measured yet say so.

Work page, mobile
MetricWordPress + ElementorAstro (headless)
Mobile PageSpeed score98Measuring after launch
Largest Contentful Paint2.1 sMeasuring after launch
Total Blocking Time0 msMeasuring after launch
JavaScript sent to the browserMeasuring after launch0 KB of my own (no framework runtime)
Requests on first loadMeasuring after launchMeasuring after launch
Total page weightMeasuring after launchMeasuring after launch
HostingPHP hosting + databaseFree static hosting (Cloudflare Pages)
Changing a projectEdit in Elementor, publishEdit fields in WordPress, publish, site rebuilds in about a minute
04 — Trade-offs

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:10 PM GMT+8.

Next project

Have a site to build or fix?

WordPress, headless or both. I reply within one business day.