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.)