Vue Renderer
@farm.js/vue connects Vue Single-File Component compilation, createSSRApp rendering, and browser
hydration to the FARMJS renderer contract. React remains the default unless the application selects
Vue.
Create an app
pnpm create @farm.js/app my-vue-app --template basic --renderer vue --typescriptFor an existing Basic app, install the adapter and Vue runtime:
pnpm add @farm.js/vue vueimport { defineConfig } from "@farm.js/core";
import { vue } from "@farm.js/vue";
export default defineConfig({
renderer: vue(),
});Pages and layouts
Vue routes use .vue files:
src/app/layout.vue
src/app/page.vue
src/app/products/[id]/page.vueUse a normal script for FARMJS route exports and <script setup> for the Vue component. A layout
renders its children through the default slot:
<script lang="ts">
import type { Metadata } from "@farm.js/core";
import "./globals.css";
export const metadata: Metadata = {
title: "FARMJS with Vue",
};
</script>
<script setup lang="ts">
defineOptions({ inheritAttrs: false });
</script>
<template>
<slot />
</template>inheritAttrs: false prevents FARMJS route props such as path from falling through to the root
DOM element. Declare the props with defineProps when the page needs them.
Hydrate interactive routes
Export hydrate = true from the route's normal script, then use Vue state and events normally:
<script lang="ts">
export const hydrate = true;
</script>
<script setup lang="ts">
import { ref } from "vue";
defineOptions({ inheritAttrs: false });
const count = ref(0);
</script>
<template>
<button type="button" @click="count += 1">Count: {{ count }}</button>
</template>FARMJS server-renders the SFC with createSSRApp and Vue's native Node or WHATWG Web stream, then
uses createSSRApp again to claim the existing browser markup.
Call FARMJS server code
API routes, endpoint schemas, server functions, middleware, cache, storage, and observability are renderer-neutral. Use the generated typed API client from the SFC:
<script setup lang="ts">
import { ref } from "vue";
import { api } from "../lib/api.generated";
const message = ref("Ready");
async function callServer() {
const result = await api.greeting.post({ body: { name: "Vue" } });
if (result.data) message.value = result.data.message;
}
</script>
<template>
<button type="button" @click="callServer">{{ message }}</button>
</template>The endpoint can call a validated createServerFn; its handler, database access, and secrets remain
in the server bundle.
Install Vue plugins
Pass an app setup module to vue() to install plugins such as Pinia, vue-i18n, or a component
library with app.use():
import { defineConfig } from "@farm.js/core";
import { vue } from "@farm.js/vue";
export default defineConfig({
renderer: vue({ app: "./src/vue-app.ts" }),
});import { defineVueApp } from "@farm.js/vue";
import { createPinia } from "pinia";
export default defineVueApp((app, { ssr }) => {
app.use(createPinia());
});Farm calls the function for every Vue app it creates: once per server render, so plugin state such
as a Pinia store is never shared between requests, and once for each hydrated root in the browser.
ssr is true on the server. State created during the server render is not transferred to the
browser; stores start from their initial state when the page hydrates. In development, edits to the
module apply on the next request.
Current boundaries
Use the Vue-native composables for reactive router, action, server-query, theme, and i18n state:
import { useAction, useRouter, useTheme } from "@farm.js/vue/bindings";
const router = useRouter();
const save = useAction(saveProduct);
const theme = useTheme();
await save({ name: "FARMJS" });
await router.push("/products");
theme.toggleTheme();The composables return Vue refs and computed values. Renderer-specific Link and form components,
fetchers, integration providers, programmatic UI routes, Markdown/MDX visual pages, the docs
adapter, and generated JSX metadata images remain React-oriented today.
The Better Auth starter includes native Vue SFC routes, composables, and forms:
pnpm create @farm.js/app my-auth-app --template better-auth --renderer vue --typescriptOther integration starter templates currently target React, so add their renderer-neutral provider code to a native Basic starter.
Run the complete example:
pnpm --filter farm-vue-renderer-example devSee the Vue renderer example, the renderer support matrix, and Vue's SSR guide.
Use Vue Single-File Components, SSR, hydration, and typed FARMJS server calls through the @farm.js/vue adapter.