DocsFramework differences
Vue
Nexy renders Vue 3 single-file components on the server, then Vue takes them over in the browser. Pages, layouts, islands and actions are the same in every framework: this page covers setup, then the parts that differ from the shared contracts.
With the modular router, Vue components are islands inside
the .nexy views a controller returns: there is no page file and no client router.
Start a project
nx new my-app --template web-fbr-vue
nx new my-app --template web-modular-vue
The template is a server-mode project with Vue islands. Run nx new my-app without a template to
answer the prompts instead: the router, the project type, whether to use client-side routing, then
the framework.
Enable Vue in an existing project
from nexy.core.models import NexyConfigModelfrom nexy.frontend import vue class NexyConfig(NexyConfigModel): useFF = vue() useAliases = {"@": "src"}import { defineConfig } from "vite";import vue from "@vitejs/plugin-vue";import nexy from "./__nexy__/vite"; export default defineConfig({ plugins: [nexy(), vue()], customLogger: nexy.log(),});nx new writes this file; Nexy writes __nexy__/vite.ts itself, so do not edit it.
| Package | Version nx new writes |
|---|---|
vue |
^3.5.33 |
@vitejs/plugin-vue |
^6.0.0 |
Rules
- One framework per project.
useFFtakes exactly one framework;useFF = [vue(), react()]stops the server at startup. - One component per file. A
.vuefile exports its component as default; the name you import it under is only the tag you write.
- Components live outside
src/routes/, usually insrc/components/, so they are not pages. - A server-mode project has no
.vuepage, and a client-mode project has no.nexypage: Nexy refuses to start and names the file. See modes.
- Components live in
src/components/, and a view imports them as islands.
Pages
In client mode (useCSR = True), a page is a .vue file.
Page component
The page is the component defined by the <script setup> block.
<template> <h1>Hello</h1></template>Dynamic segments
URL parameters reach the page as props. You can declare them using defineProps:
<script setup lang="ts">defineProps<{ slug: string }>();</script> <template> <h1>{{ slug }}</h1></template>Alternatively, use the useParams hook from @nexy/client in any component.
Layouts
Implementation
The root layout defines the document shell. Nested layouts wrap the content in their default slot.
<template> <html> <body> <header>My app</header> <main><slot /></main> </body> </html></template>Islands
In server mode, a Vue component imported into a .nexy file is an island.
Importing
Import components in the frontmatter of the .nexy file:
from "@/components/Counter.vue" import Counter<Counter start=3 />from "@/components/Counter.vue" import Counter<Counter start=3 />Hydration directives
Use the directive prop to control when the island hydrates:
client:load(default): immediatelyclient:idle: when the browser is idleclient:visible: when it scrolls into viewclient:media: when the media query matches
Actions and navigation
Calling actions
Use the useAction hook to manage the state of an action call. In Vue, the returned state
(pending, data, error) are computed refs.
<script setup lang="ts">import { ref } from "vue";import { useAction } from "@nexy/client";import { add_todo } from "@nexy/actions"; const title = ref("");const { run, pending, error, data } = useAction(add_todo, { onSuccess: () => (title.value = ""),});</script> <template> <form @submit.prevent="run({ title })"> <input v-model="title" /> <button :disabled="pending">Add</button> </form></template>
Navigation
Use the Link component for client-side transitions:
<template> <Link href="/about" active-class="active">About</Link></template>
For programmatic navigation, use the useRouter hook:
import { useRouter } from "@nexy/client"; const router = useRouter();router.push("/dashboard");
URL access
All location hooks return computed refs:
usePathname(): current pathuseParams(): dynamic segmentsuseSearchParams(): query stringuseLocation(): full location object