// A page written in the .wrn language. Route: /hello // // SSR: // `view` compiles to server-rendered HTML and is returned on the first request. // // CSR: // `state`, `{expr}`, and `@click` compile to hydrated behavior. // The browser hydrates those directives with /__wrnexus/reactive.js. page Hello { layout = "public" // Client state seed. Without this block the page is pure SSR. state count = 0 seo { title = "Hello from .wrn" description = "A WrNexus .wrn page showing SSR data, CSR hydration, cookies, sessions, and localStorage." canonical = "/hello" } // SSR data bindings run on the server before the HTML is sent. // The API itself lives in app/api/users/ssr.ts; this block only calls it // and renders the response into HTML. ssr { functions { function userNames(users) { return users.map((user) => user.name).join(", ") } } api ssrUsers GET /api/users/ssr { const visits = Number(cookies.get("hello_visits") ?? "0") + 1 cookies.set("hello_visits", String(visits), { sameSite: "Lax" }) session.set("lastHelloVisit", visits) return `${userNames(users)} - visit ${visits}` } } // Client data bindings hydrate after the first paint. The browser only sees // an opaque data-wrnexus-csr id; WrNexus calls app/api/users/csr.ts on the server. client { functions { function userNames(users) { return users.map((user) => user.name).join(", ") } } api csrUsers GET /api/users/csr { const label = localStorage.get("wrnexus.label") ?? "browser" session.set("lastClientLabel", label) return `${userNames(users)} - ${label}` } } view {
Hello, WrNexus. Count is {count}, doubled is {count * 2}.
This is fetched from app/api before HTML is sent.
This is fetched from app/api after hydration.