Migrate from Nuxt
Nuxt and Farm share Vue, file-based routing, server rendering, API routes, Vite, and Nitro
deployment output. Farm uses a different application and server contract, but the
@farm.js/vue renderer lets route UI remain in Vue Single-File Components. Preserve route URLs and
server contracts while replacing Nuxt-specific macros, composables, modules, and runtime behavior.
Using a coding agent?
Point it at
/docs/migrations/nuxt.md. That version maps every Nuxt feature to its Farm equivalent and ends with a verification checklist.
Create the Farm shell
Add Farm and the Vue renderer without removing Nuxt first:
pnpm add @farm.js/core @farm.js/vue vue
pnpm add -D @farm.js/cliCreate the smallest Farm config:
import { defineConfig } from "@farm.js/core";
import { vue } from "@farm.js/vue";
export default defineConfig({
renderer: vue(),
});Point the application scripts at Farm when the first route is ready to run:
{
"scripts": {
"dev": "farm dev",
"build": "farm build",
"start": "node .farm/.output/server/index.mjs"
}
}Map pages and layouts
Nuxt 4 normally keeps pages under app/pages; projects using the earlier layout may use pages at
the root. Both map into Farm's src/app.
| Nuxt source | Farm output |
|---|---|
app/pages/index.vue or pages/index.vue | src/app/page.vue |
app/pages/about.vue or pages/about.vue | src/app/about/page.vue |
app/pages/posts/[id].vue | src/app/posts/[id]/page.vue |
app/pages/docs/[...slug].vue | src/app/docs/[...slug]/page.vue |
app/layouts/default.vue or layouts/default.vue | src/app/layout.vue |
| nested Nuxt layouts | nested src/app/**/layout.vue files |
error.vue | the nearest error.vue and not-found.vue |
Create a root layout before moving pages:
<script setup lang="ts">
defineOptions({ inheritAttrs: false });
</script>
<template>
<slot />
</template>Keep ordinary templates, <script setup>, refs, computed values, and scoped styles. Replace Nuxt
auto-imports and macros with explicit Vue imports and Farm route exports. Use a normal
<script lang="ts"> block for named exports such as metadata and hydrate, and add
defineOptions({ inheritAttrs: false }) so route props do not fall through to the root DOM element.
See Vue Renderer for the complete SFC conventions.
Replace Nuxt navigation
| Nuxt API | Farm Vue equivalent |
|---|---|
<NuxtLink to="/about"> | <a href="/about"> |
navigateTo("/sign-in") | redirect("/sign-in") in server code |
client navigateTo() | assign window.location or use an ordinary anchor |
useRoute().params | typed page props declared with defineProps |
useRoute().query | typed page props or URLSearchParams in client code |
definePageMeta() | named metadata, generateMetadata, and route exports |
Keep dynamic segment names stable so existing links and external URLs continue to work.
Move data fetching
Classify every useFetch, useAsyncData, and $fetch call by where it should run:
| Nuxt behavior | Farm destination |
|---|---|
| server-rendered page data | server module called while rendering or an API endpoint |
| cached reusable read | createServerQuery with an explicit structured key |
| browser request to an app endpoint | generated API client or fetch |
| mutation or privileged server action | server function behind a validated API route |
| route guard data | route middleware |
Keep database clients, secrets, and privileged provider SDKs in server-only modules. Validate untrusted params, query values, form data, and API bodies before using them.
Convert server routes
Move Nitro server handlers into Farm API route modules:
| Nuxt source | Farm output |
|---|---|
server/api/hello.get.ts | src/app/api/hello/route.ts with GET |
server/api/users/[id].patch.ts | src/app/api/users/[id]/route.ts with PATCH |
server/routes/health.ts | an API route or programmatic Farm route |
server/middleware/*.ts | Farm middleware or a server plugin |
Farm handlers use Web Request and Response objects:
export async function GET() {
return Response.json({ ok: true });
}Use createEndpoint when the endpoint needs schema validation and a typed generated client.
Move middleware and plugins
Nuxt route middleware and server middleware do not share one lifecycle, so migrate them by responsibility:
- move authentication redirects and route gates into
src/app/**/middleware.ts - move global request behavior into
farm.config.tsmiddleware - move reusable server lifecycle behavior into a Farm plugin
- move provider setup into a Farm integration when it owns routes, middleware, or client context
- replace Nuxt client plugins with Vue components or Farm client plugin hooks
Repeat sensitive authorization in API routes and server functions. A page redirect is not an authorization boundary.
Move runtime configuration
Review nuxt.config.ts, app.config.ts, modules, auto-imports, aliases, and runtimeConfig
explicitly:
| Nuxt configuration | Farm destination |
|---|---|
private runtimeConfig | typed server environment variables |
runtimeConfig.public | typed public environment variables |
| app metadata | page or layout metadata exports |
| Vite plugins and aliases | the vite field in farm.config.ts when still needed |
| Nuxt modules | Farm integrations, plugins, or ordinary packages |
| auto-imported components | explicit Vue component imports |
Do not expose a private Nuxt runtime value through Farm's public environment configuration.
Verify and remove Nuxt
Run both applications during the transition and compare:
- static, dynamic, optional, and catch-all routes
- layouts, metadata, error states, and redirects
- server-rendered data and client navigation
- API status codes, headers, cookies, and response bodies
- middleware order and authorization
- image and public asset URLs
- production output on the target deployment platform
After the Farm application passes those checks, remove Nuxt, Nuxt modules, .nuxt, and
Nuxt-specific deployment configuration. Keep Vue and @farm.js/vue as application dependencies.
For source behavior, refer to Nuxt's official pages, data fetching, and directory structure documentation while auditing the original app.
Move a Nuxt application to Farm by mapping Vue pages, layouts, server routes, middleware, data, and runtime configuration.