Most quotes give you one number. Here is what sits inside it.
You ask three people what it costs to move your WordPress site to Next.js and you get three figures with nothing behind them. One says two thousand. One says nine. Neither explains the gap, so you end up picking on gut feel or on price alone.
I quote fixed prices per project, which means I have to break the work down before I can put a number on it. This is that breakdown.
What drives the number
People assume the price tracks page count. It mostly does not.
A blog with six hundred posts that all share one layout is a cheap migration. You build one template, write one loop, and the six hundredth post costs nothing more than the second. A forty page brochure site where every page was laid out by hand in a page builder is expensive, because forty pages means forty layout decisions somebody has to rebuild and check.
Five things actually move the figure:
- 01Distinct templates. How many genuinely different page layouts exist. This is the single biggest driver.
- 02Custom post types and fields. Each one needs mapping, querying and rendering. Advanced Custom Fields sprawl is where estimates go wrong.
- 03Indexed URL count. Not page count. How many URLs Google currently knows about, because every one of them needs a destination.
- 04Integrations. Forms, search, comments, memberships, payment, newsletter, analytics. Each is a small job that adds up fast.
- 05Plugin dependencies. Anything doing real work rather than styling has to be replaced with code.
Before anyone quotes you, get those five numbers. You can pull most of them yourself in ten minutes.
# How many published items, by post type. This tells you scale.wp post list --post_status=publish --format=count --post_type=postwp post list --post_status=publish --format=count --post_type=page # Every registered post type, including the custom ones a plugin addedwp post-type list --fields=name,label,public # Active plugins. The list you hand to a developer.wp plugin list --status=active --fields=name,version # How many distinct page templates the theme actually offersls -1 wp-content/themes/$(wp theme list --status=active --field=name)/*.php | wc -lNo WP-CLI access? The sitemap gives you the URL count, which is the number that matters most for the routing work.
# Total URLs across every sitemap, which is what the redirect map has to covercurl -s https://example.com/wp-sitemap.xml \ | grep -oE '<loc>[^<]+</loc>' \ | sed 's/<[^>]*>//g' \ | while read -r map; do curl -s "$map" | grep -c '<loc>'; done \ | paste -sd+ - | bcThe nine line items
Every migration I have run breaks into the same nine pieces. The proportions shift. The list does not.
1. URL audit and inventory
Pull every indexed URL from the sitemap, Search Console and the server logs, then reconcile the three lists. Server logs catch the URLs that still earn traffic but fell out of your sitemap years ago, which is exactly the set people forget.
Small job, and skipping it is how migrations lose traffic.
2. Redirect map
Old path to new path, for every URL from step one, then an automated pass that confirms each one lands on a 200 rather than a 404 or a chain. This is the work that protects your rankings, and it scales with URL count rather than template count.
3. Template build
The largest single item. One React component per distinct layout, matching the existing design unless you are redesigning at the same time, which I would advise against doing in the same project.
4. Content migration
Getting the posts, pages, media and taxonomies across. Cheap if you are running WordPress headless, because the content stays where it is and Next.js reads it over the API. Expensive if you are exporting into a different CMS, because WordPress HTML carries shortcodes, block comments and inline styles that all need cleaning.
5. Metadata and schema
Titles, descriptions, canonicals, robots rules, Open Graph images and the JSON-LD your SEO plugin was emitting. This one gets dropped from quotes constantly and then costs you rankings quietly over the following weeks.
6. Integrations
Contact forms, site search, analytics, newsletter signup, comments. Each looks trivial and each takes half a day once you include testing that the submission actually arrives.
7. Performance pass
Image handling, font loading, layout stability and the render strategy per route. Doing it during the build is much cheaper than bolting it on after launch.
8. Testing and QA
Redirect verification, metadata diffing against the live site, cross browser checks, and a real pass on a mid range phone rather than a desktop pretending to be one.
9. Deploy, documentation and handover
Environment variables, the deploy pipeline, a readme that gets a new developer running, and a recorded walkthrough. Small line, and the one that decides whether you are stuck with whoever built it.
Where the effort goes
Two things worth pulling out of that. Routing and metadata together come to twenty four percent, and they are the two items with no visible output. Nobody looks at a finished site and sees the redirect map. Cut them and the site still launches, still looks right, and quietly bleeds traffic for a quarter.
The contingency line is real work, not padding. Something always turns up: a plugin doing something undocumented, a content pattern nobody mentioned, a redirect loop from an old migration. Quotes with no contingency become change requests later.
Three worked examples
Same nine items, three different sites. The shape of the work changes more than the total.
| Brochure site | Content site | Headless content site | |
|---|---|---|---|
| Indexed URLs | Around 30 | Around 400 | Around 400 |
| Distinct templates | 6 to 8 | 5 to 6 | 5 to 6 |
| Heaviest line item | Template build | Redirect map | Template build |
| Content migration | Manual, quick | Scripted export | None, stays in WordPress |
| Editor workflow | Usually dropped | Usually dropped | Unchanged |
| Extra work | None | None | Webhook, preview mode, CMS lockdown |
| Typical span | 1 to 2 weeks | 2 to 5 weeks | 3 to 6 weeks |
Notice the brochure site has more templates than the content site despite having a fraction of the pages. That is the template point again, and it is why a small site can quote higher than a big one.
What inflates a quote
Four things reliably push the number up. Three of them are worth knowing before you ask.
- WooCommerce. Headless commerce is a different project with a different budget. Cart, checkout, payment, tax, stock and order history all have to work perfectly on day one. Often the honest answer is to leave the shop on WordPress.
- Page builders. Elementor and Divi store layout as theme specific markup. None of it travels. Every page laid out in a builder is a page somebody rebuilds by hand, which turns page count back into the main cost driver.
- Custom field sprawl. Forty Advanced Custom Fields groups across twelve post types is a mapping exercise before it is a build.
- No agreed design. If the migration is also a redesign, you are paying for two projects and the review cycles multiply. Migrate first, redesign after.
What you can safely cut
If the quote is over budget, some of it is genuinely optional.
Thin archive pages usually are. Tag archives, author pages and date archives that Yoast already marked noindex do not need rebuilding. Delete them and redirect the handful with links pointing at them.
Old content is another. If four hundred posts include a hundred and fifty that have had no traffic in two years, migrating them costs money and earns nothing. Redirect them to the closest relevant page and cut the scope.
Comments, if nobody has left one since 2021. Site search, if your analytics say almost nobody uses it.
What I would not cut, at any budget:
- The redirect map. This is the whole reason a migration is risky.
- Metadata and schema. Invisible until your rankings move.
- Testing on a real phone. Most of your traffic is on one.
- Documentation and handover. Cutting it saves days and costs you your independence.
Quotes that should worry you
Whoever you hire, including me, apply the same test. A quote should tell you what you are buying.
- 01One number and no line items. If nobody will break it down, nobody has thought it through, and the change requests are coming.
- 02No mention of redirects. The most important item in the project. Its absence tells you the quote is about building a website, not moving one.
- 03A number given before anyone looked at the site. Reasonable to give a range on a call. Not reasonable to commit to a fixed price without an audit.
- 04No contingency and no change process. Both of you will need one. Better to agree it now than to argue in week four.
- 05Nobody asks who owns the repository. Ask early. The answer should be you.
Cost and schedule move together, because most of the price is somebody's time. If the quote and the timeline do not agree with each other, one of them is wrong.
Before you commission anything, run the checks. They will tell you whether the person quoting knows what the job involves.
Related readingA WordPress to Next.js migration checklist you can hand to a developerI do this work. Send me the URL and you will get the line items and a fixed number back, or an honest recommendation to stay on WordPress and make it faster instead, which happens more often than you might expect. The migration page covers how it runs, and the contact form is the fastest way to start.
Resources
- WP-CLI command reference
Every command used above, including post list, post-type list and plugin list.
- Google: site moves with URL changes
The official guidance the redirect line item exists to satisfy.
- WordPress sitemaps
How the core sitemap is structured, which is what the URL count script reads.
- Next.js App Router docs
What the template build line item is actually building against.
- Search Console performance report
Where to export the URLs that earn traffic before you scope the redirect map.