Technical White Paper · August 2026
From HubSpot Content Hub to Next.js
An AI-executed site migration: how we rebuilt, rewrote and relaunched a 700-page site in days, and what happened to search, AI visibility and lead flow. Every number sourced, every caveat published.
One Month After Cutover
The results, first
meticulosity.com moved off HubSpot Content Hub onto a statically generated Next.js site on 8 July 2026. Measured 6 to 10 August 2026 in Google Search Console and GA4.
620
Pages indexed
From roughly 40 at the June trough
+5,335%
Impressions, 28d
119K, www property
+1,010%
Clicks, 28d
111 clicks in the window
2,060
Google AI impressions
From zero before 12 July
448
Posts rewritten
In roughly 19.5 hours
129
404 affected pages
Down from 951, still draining
$0
Media inference cost
551 images, 459 narrations
99%
GTmetrix homepage
Up from 70% on the old stack
29 pages, print-ready, no form. Or keep reading: the whole document is on this page.
What Is Inside
Contents
- 01Executive summary
- 02Part I: why we migrated
- 03Part II: how we did it
- 04The three-pass pipeline
- 05The verification culture
- 06Part III: results, one month post-cutover
- 07AI visibility, and who names us
- 08Leads, and page performance
- 09Part IV: what we would tell another team
- 10Appendix: inventory and timeline
Executive Summary
A migration was the smallest part of what changed
The platform switch is not the story. The story is what a small team with AI-assisted engineering did around the migration, in hours rather than months.
- Rebuilt every marketing page (54 at launch, 105 today) as typed, block-based content optimized for SEO, GEO and AEO.
- Rewrote the entire blog corpus for the ICP: 448 posts re-angled, restructured answer-first and fitted with AI-extraction blocks in under 20 hours of wall-clock time, via a three-pass multi-agent pipeline with adversarial verification.
- Regenerated 551 branded featured images and narrated 459 posts as audio, overnight, on local hardware, at zero inference cost.
- Cleared a multi-year backlog of technical debt: a 940-URL 404 backlog, soft-404 redirect patterns, scraped page chrome, dead links and broken share images.

The counterintuitive part: this site’s organic collapse predated the migration by months, and the migration is where every line turns back up. The next section tells that story honestly, because the lesson is bigger than a platform choice. A modern content stack only pays when you can also fix the content, at corpus scale, at AI speed.
Part One
Why we migrated
A Diamond HubSpot partner arguing itself off HubSpot Content Hub needs to show its working. Here is the measured baseline, and the honest post mortem of what actually killed the old site.
The stack we were on
meticulosity.com ran on HubSpot Content Hub: 54 marketing pages, a 551-post blog, HubSpot forms, HubSpot CTAs and HubSpot’s platform URL space. As a Diamond HubSpot partner we know the platform well, and this is not an anti-HubSpot argument. Content Hub is a fine CMS for teams that need marketing autonomy without engineering. Our problem was different: we needed surgical, corpus-wide control over rendering, structured data, URL space and performance, and we had AI-assisted engineering capacity that a closed CMS could not leverage.
Performance, four days before cutover
| Measured | Homepage | Money page |
|---|---|---|
| GTmetrix Performance | 70% | 69% |
| GTmetrix Structure | 85% | 91% |
| Largest Contentful Paint | 1.4s | 1.6s |
| Total Blocking Time | 568ms | 467ms |
| Time to First Byte | 502ms | 459ms |
GTmetrix, 4 to 6 July 2026, Seattle test server, Chrome 142 / Lighthouse 12.6.1, Broadband Fast. Money page: /agency-hubspot-support; the homepage also carried 4.17MB across 208 requests. The archived final HubSpot build, re-measured on 10 August 2026, still scores mobile 70/100: the baseline is stable, not a bad day.
Search Console told a worse story
- Indexed pages had drained to roughly 30 to 40, from about 150 in May.
- Google was crawling 50 to 100 requests per day against roughly 5,400 known URLs: a full recrawl cycle measured in months.
- Clicks on the www property fell from 295 in March to 19 in April and 8 in June. Even the brand query “meticulosity” went to zero clicks.
- The Coverage report carried roughly 940 “Not found (404)” URLs, 374 of them HubSpot platform bundle paths that Google kept recrawling on a schedule.
- Every blog post had an AMP twin and every CTA an encrypted redirect URL. At 50 to 100 crawls a day, Google was spending its residual attention on garbage.
- The tell: the old sitemap at one point listed only 31 URLs of a roughly 670-URL site.
What actually killed the old site
We reconstructed the decline from five years of data: Search Console, GA4, DataForSEO historical rankings and Semrush audit history. It runs in three phases, and the migration is not one of them.
The asset was mispriced from the start
The blog’s search footprint was consumer how-to content, ranking for queries no agency-services buyer ever types. Over the last 16 measurable months the 551-post blog produced 8,859 clicks against 15.37 million impressions, a 0.06% click-through rate, and 29 tracked key events. 42% of posts earned zero clicks.
In 2025 the SERP stopped paying for rankings we still held
Third-party rank tracking showed top-10 keyword counts at a multi-year high in November 2025 while clicks fell every single month. The Facebook cluster’s impressions stayed flat all year while its clicks fell 74%. AI Overviews and zero-click results absorbed exactly the query class the site ranked for.
Two Google core updates finished it
The December 2025 core update started the rankings slide. The March 2026 core update, 27 March to 8 April, lands exactly on the April cliff, with a portal migration churning the site in between (Semrush: errors 175 to 1,341, temporary redirects 266 to 2,005, broken internal links 112 to 629). Quality demotion collapses crawl scheduling, which drains the index, which at the extreme takes brand serving with it.
Two conclusions drove the project. First, there was no penalty to lift and nothing to wait out: the only way back into the index was to become a different site. Second, becoming a different site meant the content, not just the platform. A lift-and-shift migration of the same corpus would have moved the same liability to faster hosting.
Why Next.js specifically
- Static generation: every page pre-rendered, with no CMS runtime between Google and the HTML.
- Content as code-adjacent data: one JSON file per page, one MDX file per post. The entire corpus becomes scriptable, diffable, verifiable in CI and, decisively, operable by AI agents at scale.
- Total control of the head: metadata, canonicals, Open Graph and every JSON-LD block generated per page from typed content.
- A URL space we own: real 301s and real 410s from one config file, instead of platform bundles, AMP twins and encrypted CTA redirects.
- Performance as a design property: self-hosted fonts, inline SVG, lazy third-party embeds and near-zero client JavaScript by default.
Part Two
How we did it
Everything below was executed with Claude Code driving the work: overnight unattended builds, parallel agent fan-outs for per-page and per-post work, and scripted verification gates between every stage. Dates and durations come from the git history.
Phase 1: the overnight rebuild (2 July)
One evening’s approval started an unattended overnight run. An agent fan-out scraped every live page and post as structured JSON, plus an asset manifest, metadata, existing schema and QA screenshots. A foundation pass extracted design tokens from the live theme CSS and built a component library with a SectionRenderer mapping typed blocks to components. Then assembly: agents wrote content files only, never components, producing 54 marketing pages and 544 blog posts converted to MDX. Finally QA: build green, every internal href resolved, metadata audited against the scrape, screenshot comparison against the live originals, and a slug-parity check against the crawled URL inventory.
703
Static pages green
By morning
100
Lighthouse performance
Sampled pages, local build
100
Lighthouse SEO
Sampled pages, local build
1
Night
From a standing start
Phase 2: the SEO, GEO and AEO layer (5 to 6 July)
A dedicated pre-launch plan, 46 findings ordered by severity, implemented in a day. Zero-redirect slug parity for 592 URLs, plus a 301 map for the 46 URLs that could not be preserved, so no equity died at cutover. The full JSON-LD stack: Organization, WebSite, Service, BreadcrumbList sitewide, FAQPage wherever an FAQ block exists, and BlogPosting plus Person on every post. Answer-engine plumbing: llms.txt and llms-full.txt, a robots.txt explicitly allowing GPTBot, ClaudeBot, PerplexityBot and Google-Extended, and per-page question-form H2s matching the answer-engine query space.
The blog template was rebuilt to an AEO spec: a Quick Answer box of 40 to 60 words with a stat or named entity mandatory, Key Takeaways, an auto-generated TOC with stable anchors, up to six FAQs emitting FAQPage schema character for character, a Sources block for citations, linked bylines with Person schema, a visible updated date, reading time and an audio player.
Phase 3: the corpus rewrite (6 to 7 July, about 20 hours)
The centerpiece. Migrating 551 legacy posts unchanged would have relaunched the same content farm on faster hosting. Pass 0 was a scripted, model-free cleanup over all 544 posts, built from an empirical junk catalog: 468 broken image paths, 1,500 non-breaking-space artifacts, 724 un-decoded HTML entities, 356 bold-lines-as-headings and 179 broken heading hierarchies. Scripts fix mechanical rot; models never touch what a regex can prove. Pass 0b moved the inline FAQ sections 168 posts already carried into frontmatter, so the template renders them as accordions and emits FAQPage schema; 133 posts shipped that way. Then Search Console over 16 months, GA4 and backlink data were joined into a per-post disposition sheet: keep-and-spin, keep-as-is, merge, 301 or 410, with a target keyword for every surviving post.
Broken image paths
Pass 0, scripted
Un-decoded entities
Pass 0, scripted
Posts with FAQ schema
Pass 0b, extracted
The Rewrite Pipeline
Three passes, three different jobs
Per post, pipelined across 16 gated batches. The model that writes is never the model that verifies.
Pass 1
ICP re-angle
- Retell every generic marketing how-to from the agency-delivering-for-clients perspective, on the same URL
- Answer-first: every H2 answered in its first two sentences
- Statistics, quotations and cited sources woven in from the source library
- Writers select evidence. They never research or invent mid-rewrite
Pass 2
Distillation
- Quick Answer, 40 to 60 words, stat or entity mandatory
- Key Takeaways
- Up to six FAQs with standalone-extractable answers
- Image alt text
- Tags remapped to a rationalized 14-tag taxonomy, down from 33
- CTA selected from the library
Pass 3
Adversarial verify
- A fresh agent that never wrote the post
- Verifies facts against the canonical stats
- Traces every citation back to the source library
- Hunts fake spins
- Returns PASS, FIX or RE-ANGLE
RE-ANGLE returns the post to Pass 1. PASS releases it into the wave.
Wave gate between every batch
Build green, JSON-LD validation, internal links resolved, human spot-reads on the early waves. One commit per wave, pilot batch first.
16
Gated batches
448
Posts rewritten
Batch 1 at 21:09 on 6 July
19.5
Hours
Batch 16 at 16:24 on 7 July
2,065
Proof points
Pre-vetted source library
Includes two evidence-backfill passes that wove externally cited statistics into the early batches. Order-of-magnitude budget for the whole corpus rewrite: 6 to 9 million tokens, dominated by the Pass 1 rewrite.
Phase Four
Media at corpus scale, at zero inference cost
Both pipelines ran on local models on Apple Silicon, the same evening the rewrite finished. The marginal cost of the second run is the same as the first: nothing.
551 featured images were regenerated: a local FLUX.2 model paints the background scene from a per-post prompt written by a small local LLM, and a compositor overlays brand geometry, category label and typeset title at 1200x628. Scene prompts force the subject into the right third, because the brand overlay reveals the photo through a right-side diagonal window, and a color-rotation pass prevents runs of same-colored cards in the blog grid.
459 posts were narrated as audio: markdown stripped to speakable text, synthesized with Kokoro TTS locally, encoded to 64kbps mono MP3, uploaded to Cloudflare R2 and served by a zero-JavaScript native audio player in the post sidebar. 486 posts carry audio today, and new posts get narration as they publish.
Phase 5: cutover (8 July) and the error purge (30 July to 6 August)
DNS cut over on 8 July with slug parity, the redirect map, 410s for deliberately retired content and the sitemap submitted the same day. Post-launch, the 511-URL “Not found” export went to zero remaining: 408 URLs now answer 410, matched by shape so the open-ended set stays covered, 95 became topical 301s, 6 were live, and renamed tag archives got one-hop 301s.
A full crawl of all 709 sitemap URLs also turned up 25 posts carrying the old page’s scraped chrome inside the body, 26 unclickable CTA banner images that were pictures of buttons, 23 dead outbound links, a broken og:image on two case studies that had been making every LinkedIn share render naked, a 45MB video auto-streaming on page load, and three buttons still routing through HubSpot’s CTA redirect, including a “Download Free Ebook” button that delivered no ebook. Every fix became a permanent gate in npm test. Measurement was rebuilt on 8 and 9 August: GTM host-gated, GA4 key events cleaned, and 94% of Total Blocking Time traced to third-party tags, whose removal took homepage TBT from 1,630ms to roughly 130ms.
The Verification Culture
Speed came from agents. Safety came from gates.
Six rules, every one of them learned the expensive way. They are the difference between a corpus rewrite and a corpus incident.
Waves with gates, never big bangs
Pilot batch first, human spot-reads, scripted validation between every wave, one commit per wave. A bad wave costs one wave.
The writer never verifies
Pass 3 is always a fresh agent that has never seen the draft being checked, and never wrote it.
Deterministic work never uses a model
And the inverse is just as strict: model output always faces a deterministic check.
Suspect the checker before the content
When a checker fails at scale, it is usually broken. A validator reported 948 phantom broken links, which is what hid the 26 real ones. Every derived set now asserts non-empty.
Prove that gates fire
By injecting a violation and watching it fail. A gate that has never failed is an unverified gate, not a clean codebase.
Screenshots verify, curl is ground truth
A vision-agent fan-out re-bills every screenshot in context on every tool call. One review loop burned 488M context tokens before being redesigned text-first at roughly 5% of the cost, for the same output.
Part Three
Results, one month post-cutover
All figures from Google Search Console and GA4, captured 6 to 10 August 2026. Every claim below is a screenshot in this document, and the ones that went the wrong way are here too.
Indexation and crawl
| Metric | Pre-migration trough | Now (6 to 10 August) |
|---|---|---|
| Indexed pages | roughly 30 to 40 | 620 |
| Crawl rate | 50 to 100 requests/day | 500 to 1,200 requests/day |
| Not found (404), affected pages | 951 | 129 and draining |
| Crawled, currently not indexed | roughly 1,150 | 448 |
| Sitemap | 31 URLs at its worst | 687 clean URLs, zero noindex, zero errors |
From roughly 40 indexed pages to 620 is a 15x expansion of the surface Google is willing to serve, in four weeks, on a domain Google had all but stopped crawling.
Indexed pages
Higher is better
404 affected pages
Lower is better
Crawled, not indexed
Lower is better



Search performance
Clicks are up 1,010% and impressions 5,335% over the prior 28 days. Weekly impressions went 976, then 12,250, then 25,720 across the first three weeks after cutover, and now run at roughly 5,000 to 7,000 a day. The three-month chart is the clearest single artifact here: nothing, then the cutover date, then a wall.

All figures are the www URL-prefix property. Property choice matters and is stated on every number in this document: the apex domain property kept serving the old index through the trough, so the sharp recovery line is www-specific.
Average position got worse. That is the good news.
Average position moved from roughly 15 to roughly 25 at cutover. This is a composition effect, not a rankings drop. Before cutover, the average was computed over a tiny surviving footprint. At cutover, hundreds of pages entered the index at deep initial positions, and every one of them dragged the average down while adding impressions. The metric got worse because the business got better.

AI Visibility
From absent to present inside Google’s AI answers
The Generative AI features report in Search Console was effectively zero before 12 July. By early August it peaked near 240 impressions a day, 2,060 in the window. The ramp starts almost exactly at cutover.

| GA4 sessions from AI assistants | June | July |
|---|---|---|
| All assistants (ChatGPT, Claude, Gemini, Perplexity, Copilot) | 18 | 53 |
| claude.ai specifically | roughly 2 | 12 |
For context and against our own interest: the old site saw roughly 100 AI-referral sessions a month in mid-2025, earned by a 551-post consumer corpus at 5x today’s total traffic. The new curve is being earned by ICP pages a buyer can actually convert on, which is a different and more useful number.
Three engines, one positioning, all citing the site’s own pages
Impressions prove presence. These prove placement. All captured on 10 August 2026 on buying-intent queries.
ChatGPT“What's the best white label HubSpot agency for partner agencies?”
“My top pick right now is Meticulosity.” Ranked Best overall.
Cites the exact proof stats the rewrite wove into the site: Diamond Solutions Partner at a 5.0 marketplace rating, 12+ years a HubSpot partner, 17+ years as an agency, and working behind the scenes for partner agencies rather than competing for the end client.
Perplexity“Who provides white label HubSpot support for agencies?”
Places Meticulosity first in its Key White-Label HubSpot Providers table.
Ten sources consulted, with citations to meticulosity.com carried inline on the summary and on the Meticulosity row itself.
Claude“Who is the best white-label HubSpot agency?”
Leads its list with Meticulosity: “the most white-label-native of the bunch, it’s their whole business, not a side line”.
Reached after explicitly discounting vendor-published ranking lists, which makes the placement an outcome of the site's own pages rather than of a directory.

The Number That Pays For Everything
Leads, and page performance
We pulled the complete form-submission history from bothHubSpot portals, summed across the early-2026 portal migration, and filtered to the site’s three lead forms.
| Period | Site lead-form fills per month |
|---|---|
| 2025 monthly range | 12 to 33, averaging roughly 22 |
| Q4 2025 | 28 to 33 |
| April to June 2026, the collapse trough | 23, then 14, then 12 |
| July 2026, first month on the new site | 22, nearly double the June trough |
The honest read: one month in, lead-form volume has recovered from half-rate back to the long-term average, on impressions that are still compounding. Clicks are the leading indicator and are still climbing through the 4 to 12 week content window, so the leads line is expected to follow. That is what the 60 and 90-day updates are for.
Measurement note, because this is the money claim: GA4 event months before August 2026 undercount, since mount-fired events were silently dropped until the 9 August fix, and its conversion tag was dead from April to June. HubSpot form counts are therefore the instrument used here, summed across both portals through the migration seam.
Performance: the same-week A/B run
| Same test rig, 4 to 6 July 2026 | HubSpot (production) | Next.js (new build) |
|---|---|---|
| Homepage GTmetrix Performance | 70% | 99% |
| Homepage Structure | 85% | 99% |
| Homepage LCP / TBT / CLS | 1.4s / 568ms / 0.08 | 726ms / 41ms / 0 |
| Money page Performance | 69% | 98% |
| Money page LCP / TBT | 1.6s / 467ms | 1.0s / 90ms |
| Money page TTFB / fully loaded | 459ms / 3.6s | 95ms / 1.9s |
Since launch, third-party tag removal cut homepage Total Blocking Time a further 92%, from 1,630ms to roughly 130ms. CLS is 0 everywhere and Lighthouse SEO scores 100/100 on every page tested. Mobile lab runs on the live site vary between 52 and 97 across single runs, a documented variance under simulated throttling; field data is the metric that actually ranks and is being enabled.
Part Four
What we would tell another team
Seven things, in the order they would have saved us the most time. None of them is “pick this framework”.
The migration is the smallest part
Rehosting the same corpus buys a faster version of the same decline. Budget the rebuild of the content, not just the site.
Traffic that cannot become a customer is a liability
The old site’s biggest page ever, 5,164 clicks in its final 16 months, never produced a lead and was killed on purpose. Deliberate removals ship as 410s.
Make content machine-operable
One typed file per page and per post is what made 448 rewrites, 551 images and 459 narrations scriptable in hours. A closed CMS makes every one of those a project.
AI does the work; gates make it shippable
Multi-pass pipelines with a separate adversarial verifier, wave gates, injected-violation tests for every new check, and humans spot-reading the early waves.
Answer-first is the new on-page
Quick Answers, question-form H2s, FAQPage schema, cited statistics, entity-complete Organization schema, llms.txt and open AI crawlers. Google’s Generative AI impressions and assistant referrals both responded within weeks.
Averages lie at both ends of a migration
Keyword counts said the old site was fine while clicks halved. Average position says the new site got worse while impressions grew 50x. Judge on clicks and conversions per query class.
Instrument before you need it
The Search Console domain property, clean GA4 key events and a repeatable crawl and audit harness are what turn “it feels better” into this document.
What happens next: we publish the follow-ups
The effect window for content work at this scale is 4 to 12 weeks, which means everything above is the early return. We will publish updated figures at the 60-day and 90-day marks, mid-September and mid-October 2026, including the metrics that got worse or went nowhere. If the thesis is right, the compounding shows up there. If it is wrong, that is worth publishing too.
An independent MIT-licensed audit toolkit (claude-seo, not used to build any of the remediation) scores the money pages 84 to 92 on content quality with zero filler-phrase and zero AI-pattern flags, agent-UX 100/100, no soft-404s and no AI crawler blocked. A fresh audit on 10 August 2026 shows zero critical and zero warning regressions against the 1 August baseline.
Appendix
Technical inventory and timeline
What shipped, specifically
- Stack: Next.js App Router, TypeScript, Tailwind 4, static generation for all roughly 755 built pages. Content as typed JSON blocks (105 marketing pages) plus an MDX frontmatter contract (557 posts).
- Structured data: Organization, WebSite, Service, BreadcrumbList on 639 pages, FAQPage on 484 pages plus 133 extracted post FAQs, BlogPosting with dateModified, wordCount, articleSection and keywords, and Person with @id and sameAs.
- Answer-engine surface: llms.txt and llms-full.txt, robots.txt explicitly allowing GPTBot, ClaudeBot, PerplexityBot and Google-Extended, sitemap with lastmod on all 687 URLs.
- Redirect and 410 machinery: a 46-URL launch redirect map, a GONE list plus HubSpot bundle-path 410s matched by shape, one-hop 301s for renamed tag archives, and zero redirects pointing at index pages.
- Media: local FLUX.2 image generation with a brand compositor at 1200x628, and Kokoro TTS narration to Cloudflare R2 with a manifest-driven player.
- Validation in CI: a content validator (route parity, image and link integrity, the frontmatter contract, branded-image detection, gone-list consistency), a metadata audit against the original scrape, a full-crawl link checker and JSON-LD validation.
Timeline
Every date comes from the site repository’s git history.
2 July
overnight
Scrape and full rebuild
703 static pages building green by morning, Lighthouse 100 on performance and SEO on sampled pages.
2 to 3 July
Visual fidelity passes
The design system rebuilt from the live theme CSS; all 53 pages re-verified side by side.
5 to 6 July
SEO, GEO and AEO plan implemented
46 severity-ordered findings shipped; the blog template rebuilt to the AEO spec.
6 July
17:35
Pass 0 cleanup of all 544 posts
Deterministic junk removal across a 12-class catalog. No model involved.
6 to 7 July
448-post ICP rewrite
21:09 on 6 July to 16:24 on 7 July. 16 gated batches, three passes per post, adversarial verification on every one.
7 July
evening
551 images and 459 narrations
Local FLUX.2 and Kokoro TTS on Apple Silicon. Zero inference cost.
8 July
DNS cutover, sitemap submitted
Slug parity for 592 URLs, a 301 map for 46, and 410s for deliberately retired content.
30 to 31 July
Post-launch audit
Link, chrome, CTA and outbound purge across all 709 sitemap URLs. Validator hardened.
6 August
404 backlog cleared
The 511-URL Search Console export went to zero remaining.
8 to 9 August
Measurement stack rebuilt
Third-party tags purged; homepage Total Blocking Time down 92%.
10 August
This snapshot
620 indexed, clicks +1,010%, impressions +5,335%.
The HubSpot Agency For Agencies
We do this for other agencies’ clients too
Meticulosity is a white-label HubSpot partner working invisibly under your brand: migrations, portal audits, onboarding, automation and delivery. Everything in this document, we ran on ourselves first.