// 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 from .wrn

Hello, WrNexus. Count is {count}, doubled is {count * 2}.

SSR API data

This is fetched from app/api before HTML is sent.

Loading SSR users...

CSR API data

This is fetched from app/api after hydration.

Loading CSR users...
} // Page-local CSS is inlined with the server-rendered HTML. style { h1 { color: #2563eb; } .my-actions { display: flex; gap: 0.5rem; margin-top: 0.75rem; } .data-grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); margin: 1rem 0; } .data-panel { border: 1px solid #d1d5db; border-radius: 8px; padding: 1rem; } .data-panel h2 { font-size: 1rem; margin: 0 0 0.5rem; } .user-list { font-weight: 700; margin-top: 0.5rem; } .my-actions button { border: 1px solid #d1d5db; border-radius: 6px; padding: 0.45rem 0.7rem; } } realtime hello { on message(data) { console.log(data) } } }