// 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" } // API calls used by this page. `ssrUsers` is bound in the initial render // (its endpoint lives in app/api/users/ssr.ts); `csrUsers` is bound after // hydration in the browser (app/api/users/csr.ts). Both just call the same // users endpoint shape, so the response handling looks the same. apis { ssrUsers GET /api/users/ssr { response { const visits = Number(cookies.get("hello_visits") ?? "0") + 1 cookies.set("hello_visits", String(visits), { sameSite: "Lax" }) session.set("lastHelloVisit", visits) return `${userNames(data.users)} - visit ${visits}` } } csrUsers GET /api/users/csr { response { const label = localStorage.get("wrnexus.label") ?? "browser" session.set("lastClientLabel", label) return `${userNames(data.users)} - ${label}` } } } functions { shared function userNames(users) { return users.map((user) => user.name).join(", ") } } 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.