Blueprint & build
The build & targets
Between your source and a running application sits the CLI. It discovers your modules, builds the Blueprint, generates the entry for the chosen target, and bundles it. You configure the little that varies in one file; the rest is derived.
#What a build does
On stone build the CLI scans app/, letting your decorators and define* modules register onto the Blueprint, generates the target entry into .stone/, and produces the output in dist/. There is no registry to maintain: add a decorated file and it is in; delete it and it is gone.
stone dev # dev server with hot reload
stone build # production build (rendering deduced from adapters)
stone build --ssg # same, pre-rendered to static HTML
stone preview # serve the production build
stone export # emit static output (SSG)#Zero-config by default
There is nothing you must configure. The rendering strategy is deduced from the adapters you stacked, and the routes to pre-render are derived from the pages your app already declares. stone.config.mjs exists only for when you want to pin something.
import { defineConfig } from '@stone-js/cli'
// Zero-config: rendering is deduced from adapters, SSG is a build flag
// (stone build --ssg), and pre-rendered routes come from your own pages.
export default defineConfig({})The principle
A framework that already knows your adapters and your routes should not make you restate them. Defaults are deduced from what the app declares; configuration is a choice, never a tax.
In Stone.js
Rendering follows the adapters: a browser adapter alone is a SPA; a backend adapter alone is SOR (server-only rendering); both give SSR, and --ssg pre-renders that same SSR at build time. The pre-render set is collected from your scanned page routes, so adding a page adds a static file, with nothing to keep in sync.
#Pinning it, if you want to
Every option stays reachable. Pin the rendering mode, add extra static paths (e.g. expanded parameterized routes), or tune the bundlers, all optional.
export default defineConfig({
builder: {
target: 'react', // 'react' | 'service' (usually deduced)
rendering: 'ssg', // pin instead of using the --ssg flag
ssg: { routes: ['/sitemap'] } // ADDED to the auto-derived routes
}
})#Config reference
| Setting | Type | Default | Description |
|---|---|---|---|
| builder.target | 'react' | 'service' | · | A frontend (React) app, or a backend service. Usually deduced. |
| builder.rendering | 'csr' | 'ssr' | 'ssg' | · | Pin the rendering mode. Deduced from adapters when omitted. |
| builder.ssg.routes | string[] | · | Extra static paths, ADDED to the routes auto-derived from your pages. |
| builder.lazy | boolean | true | Per-route code splitting (and the scanned routes that feed SSG). |
| builder.imperative | boolean | · | Favour the imperative (define*) programming style. |
| builder.dotenv | object | · | How .env files are loaded. |
| builder.input | { app, views, mainCSS } | · | Module-discovery globs and the auto-linked entry stylesheet. |
| builder.browser.excludedModules | string[] | · | Modules to keep out of the browser build (server-only code). |
| public | string | 'public' | A directory copied verbatim to the build root. |
| output | string | · | The build output path. |
| builder.vite / builder.rollup | passthrough | · | Escape hatches to the underlying Vite (frontend) and Rollup (service) configs. |
Two escape hatches matter when you outgrow the defaults: builder.vite and builder.rollup pass options straight to the bundlers, and builder.browser.excludedModules keeps server-only code (a database driver, a secret) out of the client bundle.
#The .stone directory
.stone/ is generated: the entry that wires your discovered modules for the chosen target, plus intermediate artifacts. It is derived output, regenerated on every build. Never edit it or commit it; deleting it is safe.