Guides
Server and Client Components
Keep data access on the server while adding reusable UI and interactive controls.
Combine server-rendered UI with interactive Client Components without moving data access into the browser. The example pairs a greeting component with a counter. It shows where each kind of component belongs.
Choose a component for the task
| Task | Use |
|---|---|
| Read services and render data | A Page or EFFRONT.Component |
| Handle clicks, input, or local state | A Client Component |
| Submit data to the server | A Server Function |
Keep data access on the server. Add Client Components only where users interact with the page.
Reuse server-rendered UI
In src/entry.effront.tsx from Routes, define Welcome.
Then replace HomePage:
// src/entry.effront.tsx: add before HomePage.
const Welcome = EFFRONT.Component.make({
render: ({ name }: { readonly name: string }) => Effect.succeed(<p>Hello, {name}.</p>),
});
// Replace HomePage.
const HomePage = EFFRONT.Page.make({
render: () => Effect.succeed(<Welcome name="Ada" />),
});Open / to see Hello, Ada.
For data-backed UI, read application services inside the Effect returned by render.
Add an interactive control
Create src/components/counter.tsx with "use client" as its first statement:
"use client";
import { useState } from "react";
export function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount((value) => value + 1)}>Count: {count}</button>;
}Import it in src/entry.effront.tsx.
Then replace HomePage again:
// src/entry.effront.tsx: add to the imports.
import { Counter } from "./components/counter";
// Replace HomePage.
const HomePage = EFFRONT.Page.make({
render: () =>
Effect.succeed(
<>
<Welcome name="Ada" />
<Counter />
</>,
),
});Open /.
Click Count: 0 to increase the counter.
Effront renders the Welcome component on the server.
Refer to React's "use client" reference for the boundary rules.