Stone.jsDocs
Paradigm

Frontend

Rendering: CSR, SSR, SSG

CSR, SSR and SSG are not three ways to write your app. They are three ways to resolve the same pages. You pick one in configuration (and, for SSR, by which adapters you stack); the pages you wrote stay identical.

#Choosing a strategy

stone.config.mjsjs
export default defineConfig({
  rendering: 'ssg'   // 'csr' | 'ssr' | 'ssg'
})
StrategyTypeDescription
csrclientA pure SPA, rendered in the browser. Ship the Browser adapter.
ssrserver + clientRendered per request on a server/edge adapter, then hydrated in the browser.
ssgbuild + clientPre-rendered to static HTML at build (list the routes), then hydrated on load.

#SSR is a superposition

There is no "SSR mode" to write for. Stack a server (or edge) adapter with the Browser adapter: the server context resolves the first paint, the browser context resolves everything after. The pages never know which one ran them.

app/Application.tsdeclarativeimperative
import { StoneApp } from '@stone-js/core'
import { Routing } from '@stone-js/router'
import { UseReact } from '@stone-js/use-react'
import { Browser } from '@stone-js/browser-adapter'
import { NodeHttp } from '@stone-js/node-http-adapter'

@Browser()     // resolves the interactive app in the browser
@NodeHttp()    // ...and the first paint on the server
@UseReact()
@Routing()
@StoneApp({ name: 'tasks-ui' })
export class Application {}
import { defineStoneApp } from '@stone-js/core'
import { routerBlueprint } from '@stone-js/router'
import { useReactBlueprint } from '@stone-js/use-react'
import { browserAdapterBlueprint } from '@stone-js/browser-adapter'
import { nodeHttpAdapterBlueprint } from '@stone-js/node-http-adapter'

export const App = defineStoneApp(
  { name: 'tasks-ui' },
  [routerBlueprint, useReactBlueprint, browserAdapterBlueprint, nodeHttpAdapterBlueprint]
)

#SSG routes

Static generation pre-renders the routes you list. Parameterised routes are listed explicitly. Everything hydrates on load, so the page is interactive after the first paint.

stone.config.mjsjs
export default defineConfig({
  rendering: 'ssg',
  ssg: { routes: ['/', '/tasks', '/tasks/1', '/about'] }
})

#SOR: server-only, zero client JS

There is a fourth option the superposition model gives you almost for free. Render on a server or edge adapter but do not stack the Browser adapter: the server produces the HTML and there is nothing to hydrate, so no client bundle ships at all. This is Server-Only Rendering (SOR), the zero-JavaScript mode for content that does not need interactivity, a marketing page, a document, an email view.

ModeTypeDescription
SSR (hydrated)server + BrowserServer render, then the browser hydrates: interactive.
SOR (server-only)server, no BrowserServer render, no client bundle, no hydration: zero JS.

#Streaming SSR

For large pages, the server can stream HTML as it renders instead of buffering the whole document, so the browser starts painting sooner. Streaming is a render option on the server adapter; the pages you wrote do not change.

#Hydration and the snapshot

On SSR and SSG, the server render serialises the page's data into the HTML as a snapshot; the browser hydrates from it instead of re-fetching, so the first interaction is instant and the loader does not run twice. This is automatic; you write pages, not hydration code.


Stone.js

Your app exists in every runtime. Until you run it.

An open-source project by Stone Foundation
Created by Mr. Stone (Evens Pierre)