Getting Started
Davaux is an SSR-first JSX framework for Node.js. It gives you file-based routing, server-rendered JSX pages, and zero client-side JavaScript by default. When you need interactivity, you opt in to islands — isolated client components that hydrate independently while the rest of the page stays as plain HTML.
Requirements
- Node.js 22 or later
- npm 10+
Scaffold a new project
The fastest way to get started is with npx davaux create:
npx davaux create my-app
cd my-app
npm install
The scaffolded project includes a basic file structure, a davaux.config.ts, and example routes so you can see the conventions in action right away.
Project structure
A typical Davaux project looks like this:
my-app/
├── davaux.config.ts # Framework configuration
├── package.json
├── tsconfig.json
└── src/
├── islands/ # Client-side interactive components
│ └── Counter.tsx
└── routes/ # File-based routing root
├── _layout.tsx # Root layout (HTML shell)
├── index.page.tsx # → GET /
└── about.page.tsx # → GET /about
Everything under src/routes/ becomes a URL. Files named _layout.tsx, _middleware.ts, and _error.tsx are framework-reserved and do not map to URLs.
Running the dev server
npm run dev
# or: npx davaux dev
The dev server starts on http://localhost:3000 by default and watches your source files for changes. When a route file changes the server reloads automatically; when a new route is created or deleted the router re-scans.
Creating your first page
Pages are TypeScript/TSX files that export a default handler via definePage. The handler receives a request context object and returns JSX (or a redirect):
// src/routes/hello.page.tsx
import { definePage } from 'davaux'
export default definePage((ctx) => {
const name = ctx.query.get('name') ?? 'world'
return (
<div>
<h1>Hello, {name}!</h1>
<p>This page is server-rendered.</p>
</div>
)
})
Visit http://localhost:3000/hello?name=Davaux to see it rendered.
Page handlers can be async — you can fetch data, read from a database, or call any async API:
import { definePage } from 'davaux'
export default definePage(async (ctx) => {
const res = await fetch('https://api.example.com/posts')
const posts = await res.json() as { id: number; title: string }[]
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
)
})
Setting the page title
Use ctx.head to set the title and description for the current page. Your root layout reads these values to render the appropriate <title> and <meta> tags:
import { definePage } from 'davaux'
export default definePage((ctx) => {
ctx.head.title = 'Hello — My App'
ctx.head.description = 'A warm greeting page.'
return <h1>Hello!</h1>
})
Building for production
Server-side rendering (SSR):
npm run build # compiles to dist/
davaux start # serves dist/ with Node.js
Static site generation (SSG):
davaux static # pre-renders all pages to out/
The out/ directory is a fully static tree of HTML files that can be deployed to any static host — no Node.js required at runtime.