WordPressCustom ThemeGutenbergPerformanceDX

WordPress Rebuild

Custom Theme & Gutenberg Block System

Replacing a heavy page-builder site with a code-first custom theme — 36 native Gutenberg blocks, a sitewide search REST endpoint, /llms.txt for AI crawlers, schema-rich markup, and an editor experience that mirrors the frontend.

36
native blocks
80 → 99
Lighthouse perf
−87%
hub page bytes
The Challenge

The previous site sat on a generic page-builder theme — Elementor, Yoast plugin soup, and dozens of third-party assets. The home page pulled 325 network requests and transferred 5.9 MB before the visitor scrolled. Mobile navigation was broken. Schema was bolted on by plugins and frequently duplicated. The editor experience punished anyone who tried to actually write a page.

The Approach

Six decisions that replace the page-builder stack

Native Gutenberg, no page builders

Every block is registered through the WordPress block API — no Elementor, no Divi, no shortcode soup. Cleaner markup, predictable updates, no vendor lock-in.

Editor mirrors the frontend

Each custom block ships PHP render + matching editor preview via ServerSideRender wrapped in <Disabled>. Writers compose pages while seeing the real layout — not an abstract form.

Schema-first markup

MedicalProcedure, FAQPage, Person, Review[], AggregateRating, VideoObject, BreadcrumbList — emitted via wpseo_schema_graph filter. Explicit deduplication so Yoast and our emitter never collide.

Server-rendered navigation

Header is PHP, not JS — ~30 hub and treatment links are visible to Bing, accessibility scanners, and LLM crawlers from the first byte.

Sitewide search as a REST endpoint

Custom /wp-json/db/v1/search returns 4 buckets (treatments, concerns, articles, topics) with synonym support. Object-cached for 5 min, auto-invalidates on save_post / edited_term.

AI-friendly out of the box

/llms.txt and /llms-full.txt expose the site index in the emerging plain-text convention for Anthropic, OpenAI, and Perplexity crawlers. Cached for an hour.

Custom Gutenberg Blocks

36 blocks built on the WordPress block API

Each block is styled in the editor to match how it looks on the frontend — editors see the real layout while writing. Below: the most-used blocks across the live site — each preview carries its live page count and any structured data it emits.

Editor-matched previews

What the blocks actually look like

Blocks that emit structured data carry a JSON-LD badge — schema is wired in at render, not bolted on by a plugin.

doctor-card156+ pages

Doctor authority card

Photo + 3-line credential stack. Contributes a Person node to JSON-LD via the schema graph filter.

pull-quote117+ pages

Display pull-quote

Cormorant Garamond italic with left terra border. Visual reset between long text blocks.

reference-list113+ pages

Citations + DOI

Auto-detects bare DOI, DOI URL, or source URL. Renders as a proper ordered citation list.

comparison-table109+ pages

Responsive feature matrix

Real <table> on desktop, swipe-card stack on mobile. Eyebrow + heading + optional footer.

faq109+ pages

FAQ accordion

Emits FAQPage schema — explicitly deduplicates with Yoast so a page never ships two FAQPage nodes.

alert-box102+ pages

Tone-aware callout

Info / warning / clinical / contraindication / tip. Each tone gets its own Lucide icon by default.

feature100+ pages

Universal text + media

Image or video, left or right, eyebrow + title + paragraphs + bullets + CTA. Replaced 4 legacy blocks.

spec-card95+ pages

At-a-glance specs

5-column responsive strip (2 mobile → 3 sm → 5 lg) with vertical dividers between columns.

timeline80+ pages

Procedure flow / recovery

Two variants — milestones (horizontal dots) and steps (vertical numbered circles).

cta-block88+ pages

End-of-article CTA card

Pink-soft panel with display-serif title, NAP one-liner, primary Book button, outlined Call button. Auto-pulls clinic NAP from theme options.

candidacy-checklist66+ pages

Good fit / not a fit

Two-column eligibility list with a {book_url} token in the footer that resolves to the booking deep-link helper.

Plus 25 more — section-nav helpers, hub navigators (path-router, concern-router, face-zone-explorer), cross-sell strips, CTA bands, and content scaffolds.

Beyond Blocks

The theme around the blocks

8

Custom templates

single-treatment, single-enhancedcategory (hub), single-enhancedcategory-tag, single (blog), archive, page-home-front, page-medical-aesthetics, page-price-list — each thin, with heavy work in /parts.

3

New CPTs

treatment (flat-URL /{slug}/), enhancedcategory (decision hubs), review (admin-only, tagged by methods/concerns for auto-pull into reviews carousel).

4

Taxonomies powering auto-hubs

treatment_methods, treatment_concerns, skin_types, topics — plus admin UI for sort order and short hub intro term-meta.

9

Mu-plugins

Lightweight CPT registration, 301 redirects, ACF auto-sync for brand-cards, NSF schema override (WebPage → CollectionPage), tag→hub redirects.

3

Navigation variants

Three nav variants auto-picked from menu structure: simple link, simple dropdown, mega menu (rail + grid). Mobile: slide-in right drawer with <details> accordions and a sticky Book button.

5★

Feedback funnel

Standalone db-feedback plugin: 5★ routes to Google reviews, lower scores capture comment + email to a custom table for follow-up.

Performance — Network

Before / After, captured the same way both times

Desktop 1440×900, cold cache, no throttling. Old theme and post-migration (same domain) captured in Chrome after a full-page scroll — so every lazy-loaded image, tracking pixel, and downstream asset is included. Same URL, same browser, same conditions — only the theme under the hood differs.

Home Page

The most-trafficked page

Requests−40%
was
325
now
196
Transferred (gzip wire)−41%
was
5.9 MB
now
3.5 MB
Resources (decoded)−23%
was
14.1 MB
now
10.9 MB
DOMContentLoaded−95%
was
3.56 s
now
181 ms
Load−87%
was
3.63 s
now
456 ms

The new home added a Google Map, more hero images, and a full tracker stack (GA4, GTM, Cloudflare Insights, booking widget) — and still ships −41% transferred and −23% resources versus the old theme. DCL −95%, Load −87%. A caching-worker rewrite trimmed bytes and requests further.

Treatment Page · PDO Thread Lift

The money page — heavy media

Requests−45%
was
320
now
175
Transferred (gzip wire)−73%
was
12.8 MB
now
3.5 MB
Resources (decoded)−49%
was
21.2 MB
now
10.9 MB
DOMContentLoaded−45%
was
395 ms
now
218 ms
Load−84%
was
1.89 s
now
299 ms

Treatment pages are the heaviest in the catalogue — hero photos, FAQ, schema, video. The rebuild still drops Transferred −73% and Load −84%. A WebP-on-demand pipeline (next pass) will trim Transferred another 30–50%.

Hub Page · Injections

The biggest reduction in the study

Requests−91%
was
292
now
26
Transferred (gzip wire)−87%
was
4.4 MB
now
569 KB
Resources (decoded)−89%
was
12.7 MB
now
1.4 MB
DOMContentLoaded−49%
was
338 ms
now
172 ms
Load−68%
was
1.46 s
now
467 ms

The hub is where the old stack’s overhead is most visible — the page-builder tooling loads its full asset payload even on a content-light orientation page. The rebuild ships only what the hub actually uses.

Lighthouse Scores

Lab scores, three pages, two devices

Lighthouse 13.0.2. Gauges use the official Lighthouse palette so they read instantly — green is Good, amber Needs Improvement, red Poor. This is the standard Lighthouse anyone can re-run locally in Chrome DevTools.

Desktop · custom throttling

Home

100
Perf
was 80+20
100
A11y
was 98+2
100
Best Pr.
was 73+27
100
SEO
was 92+8
FCP−55%
was
1.1 s
now
0.5 s
LCP−58%
was
1.9 s
now
0.8 s
TBT0
was
0 ms
now
0 ms
CLS0
was
0.00
now
0.00
Speed Index−90%
was
5.0 s
now
0.5 s

Four 100s on the money page. The last SEO holdout — the uncrawlable-link check — closed on the follow-up pass. Best Practices climbed from 73 with the third-party trim.

Treatment · PDO Thread Lift

100
Perf
was 95+5
100
A11y
was 91+9
100
Best Pr.
was 73+27
100
SEO
was 100
FCP−43%
was
0.7 s
now
0.4 s
LCP−64%
was
1.4 s
now
0.5 s
TBT0
was
0 ms
now
0 ms
CLS0
was
0.00
now
0.00
Speed Index−43%
was
0.7 s
now
0.4 s

Four 100s on the heaviest money page in the catalogue. Performance 95 → 100, Accessibility 91 → 100 after the touch-targets and link-semantics pass, Best Practices 73 → 100 from the third-party trim. LCP 1.4 → 0.5 s.

Hub · Injections

100
Perf
was 93+7
100
A11y
was 98+2
100
Best Pr.
was 73+27
100
SEO
was 100
FCP−50%
was
0.6 s
now
0.3 s
LCP−65%
was
1.7 s
now
0.6 s
TBT0
was
0 ms
now
0 ms
CLS0
was
0.00
now
0.00
Speed Index−67%
was
0.9 s
now
0.3 s

Four 100s — clean sweep. Google Lighthouse fires its own confetti animation only when all four categories are perfect, and this page unlocks it. The page-shape we design toward for the rest of the catalogue.

Mobile · Moto G Power, Slow 4G · median of 3 runs

Home

100
Perf
was 56+44
100
A11y
was 98+2
100
Best Pr.
was 73+27
100
SEO
was 92+8
FCP−38%
was
1.6 s
now
1.0 s
LCP−72%
was
6.4 s
now
1.8 s
TBT−95%
was
800 ms
now
40 ms
CLS0
was
0.00
now
0.00
Speed Index−74%
was
3.8 s
now
1.0 s

Four 100s on mobile Slow 4G — the last card to sweep the board. Fixing the hero image srcset closed the final Perf points. LCP 6.4 → 1.8 s (−72%), TBT 800 → 40 ms (−95%). Every page-device combination in the study now runs a clean 4×100.

Treatment · PDO Thread Lift

100
Perf
was 79+21
100
A11y
was 90+10
100
Best Pr.
was 73+27
100
SEO
was 100
FCP−32%
was
1.9 s
now
1.3 s
LCP−70%
was
5.3 s
now
1.6 s
TBT−43%
was
70 ms
now
40 ms
CLS0
was
0.00
now
0.00
Speed Index−32%
was
1.9 s
now
1.3 s

Four 100s on the heaviest money page in the catalogue — mobile Perf unlocked by a hero-image preload, then Accessibility (contrast + touch targets) followed. LCP 5.3 → 1.6 s (−70%, deep in Good), TBT down to 40 ms.

Hub · Injections

100
Perf
was 78+22
100
A11y
was 98+2
100
Best Pr.
was 73+27
100
SEO
was 100
FCP−48%
was
2.1 s
now
1.1 s
LCP−79%
was
5.2 s
now
1.1 s
TBT−33%
was
60 ms
now
40 ms
CLS0
was
0.00
now
0.00
Speed Index−59%
was
3.2 s
now
1.3 s

Four 100s on mobile — the first mobile card in the study to sweep the board. LCP 5.2 → 1.1 s (−79%), FCP and LCP effectively tied at 1.1 s, TBT down to 40 ms. The A11y contrast fix landed and unlocked this card entirely.

Bottom line

The whole study, in four numbers.

lighter on bytes
Hub page · 4.4 MB → 569 KB transferred
−87%
Home Load
3.63 s → 456 ms · what users actually feel
56 → 100
Mobile Perf · Slow 4G
Lighthouse score on the page that hurt the most
8,980
real RUM visits
30 days · Mobile ≈ Desktop in p75 page load

Across three pages and two devices, the rebuild does one thing consistently — it gets out of the way. Less code, lighter payload, cleaner schema. Every regression on the page is named and explained — every win is real.

Real-User Metrics — Cloudflare RUM

Lab is a simulation. This is what people actually felt.

Lighthouse is lab. Cloudflare RUM is real users, on their actual devices and networks. This is what Google's CrUX database also captures — and what shapes the SEO ranking signal for Core Web Vitals. 30-day window across real visits.

1,614 ms
US — primary market
P75 page load · 5,460 visits
2.67 ≈ 2.64 s
Mobile ≈ Desktop
Same speed on both — rare in the wild
1,684 ms
iOS / Safari users
2,100 visits · near-edge of “Good”
8,980
Real visits (30 days)
Statistically significant sample

p75 page load · 30-day trend

The bar under the chart is the CWV rating over time. The site sits in orange ("Needs Improvement") for the first ⅔ of the month, then flips to green ("Good") on Sun 21 Jun — the day the booking widget went lazy + GTM was cleaned up. Three days later p75 drops below 1.5 s with no spikes.

0s1s2s3sGood < 1.5s
CWV rating · 1 Jun▲ flips Good · Sun 21 Jun30 Jun

By geography & device · p75

The slow rows on the right side of the chart — Singapore, China, India, Windows — are small samples on far-from-edge networks or older hardware. That’s connectivity, not the rebuild. The numbers that actually describe your customers are US, Mexico, iOS, and Linux.

US — primary1,614 ms
iOS / Safari1,684 ms
China5.7 s
Windows5.8 s
Singapore6.1 s
India7.6 s
dashed line = “Good” threshold (< 2.5 s)

Why this is stronger than Lighthouse

Lighthouse simulates one device on one connection at one moment. RUM aggregates thousands of real sessions — old phones, slow Wi-Fi, cold caches, every combination. The numbers you see here are what your customers actually experience.

What Google does with these numbers

Chrome ships these measurements to Google’s CrUX dataset. CrUX feeds the Core Web Vitals signal in Search ranking. The greener the CWV bar, the stronger the ranking lift — visible in a 28-day rolling window.

Editor Experience

Writing shouldn't feel like fighting the tool

URL fields autocomplete inside a chosen CPT and auto-pull image + title + excerpt from the linked post. Image fields write the attachment's alt text into the block's target field so authors set alt once, not per block. Editors compose pages while seeing the real frontend layout.

Tech Stack
WordPressPHPTailwind CSS@wordpress/elementServerSideRenderREST APIACFYoast SEO interopschema.org JSON-LDMU-Plugins
Business Impact

The rebuild isn't cosmetic — the content engine ships more, faster.

Fewer assets means lower latency. Cleaner markup means stronger schema and better LLM crawlability. A real editor experience means doctors and content leads can publish without a developer in the loop. Concrete impact numbers will land here once measured.

Customer voice

What the founder says.

Dr. Natalya Borakowski, NMD — founder of Desert Bloom Skincare
I paid less than I got back — and the investment had paid itself off within a couple of months. Every metric grew. And so did our citations and brand recognition.
Dr. Natalya Borakowski, NMD
Founder · Desert Bloom Skincare · Scottsdale, AZ
And your site?

You scrolled this far for a reason.

You’re asking yourself the same questions every business owner asks at some point. The difference is — there are answers, and they’re simpler than you think.

Is my site actually fast — or just fast for me, sitting on fiber next to the server?
Do Google and AI assistants see what I want them to see — or are they reading plugin noise?
Am I losing customers because the booking form takes three seconds to wake up?
Is my WordPress holding me back — or have I just gotten used to it?
★ Free first read

Stop guessing. Find out where your site actually stands.

Drop your URL and email. We’ll come back with a first read of how fast your site loads, what Google and AI crawlers actually see, and whether a rebuild would pay for itself. Faster than you think — and cheaper than you can imagine.

No newsletter, no sales sequence. One human reply, fast.