cd /news/ai-agents/i-built-an-ai-agent-that-migrates-ne… Β· home β€Ί topics β€Ί ai-agents β€Ί article
[ARTICLE Β· art-13518] src=dev.to pub= topic=ai-agents verified=true sentiment=↑ positive

I built an AI agent that migrates Next.js Pages Router to App Router

A developer built migrate-bot, an AI agent that automates the end-to-end migration of Next.js Pages Router projects to App Router. The tool handles semantic changes including converting `getStaticProps` to async Server Components, `next/router` to `next/navigation`, and restructuring `pages/` to `app/` with dynamic routes. The serverless pipeline runs through stages from queuing to PR readiness, with automatic refunds triggered if a migration fails mid-process.

read2 min publishedMay 25, 2026

Most Next.js teams have a Pages Router β†’ App Router migration sitting in their backlog. It's mechanical but careful work, and it keeps getting deprioritized. I built migrate-bot to automate it end-to-end, and this post is about how it works under the hood.

App Router isn't just "move files to a new folder". The semantic changes:

getStaticProps

/ getServerSideProps

β†’ async

Server ComponentsgetStaticPaths

β†’ generateStaticParams

next/router

β†’ next/navigation

(useRouter

/ usePathname

/ useSearchParams

)next/head

β†’ the Metadata API (export const metadata

)pages/_app.tsx

  • pages/_document.tsx

β†’ app/layout.tsx

pages/api/x.ts

(single handler) β†’ app/api/x/route.ts

(export async function GET/POST/...

)pages/

β†’ app/

restructure, including [slug]

dynamic routesThe whole thing runs serverless + ephemeral:

queued β†’ analyzing β†’ planning β†’ migrating β†’ verifying β†’ pr_ready
                                                ↓ (on failure)
                          aborted_blocker β†’ refunding β†’ refunded

Each transition is persisted to D1 so every job is observable, and a mid-pipeline crash transitions to aborted_blocker

β†’ automatic refund rather than leaving the customer charged for nothing.

Early on, every repo with a pages/_document.tsx

failed. The planner maps both _app.tsx

and _document.tsx

to the same target (app/layout.tsx

), and my migrate step recorded the second one as a "failed task" when it detected the target was already written. The pipeline treated any failed task as fatal β€” so the whole migration aborted.

The fix was to distinguish intentional skips (planned target collisions) from real failures (the LLM aborting or erroring). I added a skippedTaskIds

field separate from failedTaskIds

, and surfaced the skip in the PR description so the customer knows to manually merge any custom <Html>

attributes from their _document.tsx

.

Since this rewrites real production code, the trust mechanisms matter:

next build

) can't pass for reasons attributable to the service.It's live at migrate-bot.dev. Pricing is per-repo by file count ($99 / $249 / $499). I'd genuinely value feedback on the approach β€” especially the pricing shape and the draft-PR + refund trust model.

(Currently not offered to EEA/UK/Switzerland residents due to GDPR territorial scope; revisiting post-launch.)

── more in #ai-agents 4 stories Β· sorted by recency
── more on @next.js 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/i-built-an-ai-agent-…] indexed:0 read:2min 2026-05-25 Β· β€”