DocsFramework differences
React
Nexy renders React 19 components on the server, then React hydrates them 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, React 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-react
nx new my-app --template web-modular-react
The template is a server-mode project with React 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 React in an existing project
from nexy.core.models import NexyConfigModelfrom nexy.frontend import react class NexyConfig(NexyConfigModel): useFF = react() useAliases = {"@": "src"}import { defineConfig } from "vite";import react from "@vitejs/plugin-react";import nexy from "./__nexy__/vite"; export default defineConfig({ plugins: [nexy(), react()], customLogger: nexy.log(),});nx new writes this file; Nexy writes __nexy__/vite.ts itself, so do not edit it.
| Package | Version nx new writes |
|---|---|
react, react-dom |
^19.2.5 |
@vitejs/plugin-react |
^5.2.0 |
@types/react, @types/react-dom |
dev dependencies |
Rules
- One framework per project.
useFFtakes exactly one framework;useFF = [react(), vue()]stops the server at startup.
- Pages are
.tsx. React owns.tsxand.jsxfor components, but only a.tsxfile undersrc/routes/becomes a page. - Components live outside
src/routes/, usually insrc/components/, so they are not pages. - A server-mode project has no
.tsxpage, 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 .tsx file.
Page component
A page is the default export of the file. If no default export exists, Nexy picks the first named export.
export default function Home() { return <h1>Hello</h1>;}Dynamic segments
URL parameters are available via the useParams hook:
import { useParams } from "@nexy/client"; export default function Post() { const { slug } = useParams<{ slug: string }>(); return <h1>{slug}</h1>;}Layouts
Implementation
The root layout defines the document shell. Nested layouts wrap the content below them.
import type { ReactNode } from "react"; export default function RootLayout({ children }: { children: ReactNode }) { return ( <html> <body>{children}</body> </html> );}Islands
In server mode, a React component imported into a .nexy file is an island.
Importing
Import components in the frontmatter of the .nexy file:
from "@/components/Counter.tsx" import Counter<Counter start=3 />from "@/components/Counter.tsx" 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:
import { useAction } from "@nexy/client";import { add_todo } from "@nexy/actions"; const { run, pending, error, data } = useAction(add_todo);// ...<button onClick={() => run({ title: "New Task" })}>Add</button>
Navigation
Use the Link component for client-side transitions:
import { Link } from "@nexy/client"; <Link href="/about">About</Link>
For programmatic navigation, use the useRouter hook:
import { useRouter } from "@nexy/client"; const router = useRouter();router.push("/dashboard");
URL access
usePathname(): current pathuseParams(): dynamic segmentsuseSearchParams(): query stringuseLocation(): full location object