Getting Started
Scaffold a project or drop hadars into an existing React app.
Scaffold a new project
Creates a project with TypeScript and Tailwind already wired in:
npx hadars new my-app
cd my-app
npm install
npm run devManual installation
Add hadars to an existing project:
npm install hadars1 — hadars.config.ts
Create a config file at the root of your project. The only required field is entry:
import type { HadarsOptions } from 'hadars';
const config: HadarsOptions = {
entry: 'src/App.tsx',
port: 3000,
};
export default config;For a multi-core production server:
import os from 'os';
import type { HadarsOptions } from 'hadars';
const config: HadarsOptions = {
entry: 'src/App.tsx',
port: 3000,
workers: os.cpus().length,
};
export default config;2 — src/App.tsx
Export a default React component and an optional getInitProps function. Place HadarsHead anywhere in the tree — no wrapper component needed.
import React from 'react';
import {
HadarsHead,
type HadarsApp,
type HadarsRequest,
} from 'hadars';
interface Props {
user: { name: string; email: string };
}
const App: HadarsApp<Props> = ({ user }) => (
<>
<HadarsHead status={200}>
<title>Hello {user.name}</title>
<meta name="description" content="My hadars app" />
</HadarsHead>
<main>
<h1>Hello, {user.name}!</h1>
<p>{user.email}</p>
</main>
</>
);
// Runs on the server for every request.
export const getInitProps = async (req: HadarsRequest): Promise<Props> => {
const user = await db.getUser(req.cookies.session);
return { user };
};
export default App;Static files
Place images, fonts, favicons, robots.txt, and any other static assets in a static/ directory at your project root. hadars serves them automatically — no config needed.
my-app/
├── static/
│ ├── logo.png
│ ├── favicon.ico
│ └── robots.txt # served at /robots.txt
├── src/
│ └── App.tsx
└── hadars.config.ts3 — CLI
# Development server with React Fast Refresh HMR
hadars dev
# Production build — client + SSR compiled in parallel
hadars build
# Serve the production build
hadars run
# Bundle into a single self-contained Lambda .mjs
hadars export lambda [output.mjs]HadarsRequest
The request object passed to getInitProps extends the standard Request with:
interface HadarsRequest extends Request {
pathname: string; // e.g. "/blog/my-post"
search: string; // e.g. "?page=2"
location: string; // pathname + search
cookies: Record<string, string>;
}Lifecycle hooks
Beyond getInitProps, you can optionally export:
ExportRuns onPurpose
getInitPropsserverFetch data from the incoming request. Return props passed to the app component.getFinalPropsserverStrip server-only fields before props are serialised into the page JSON for the client.getClientPropsclientEnrich props with browser-only data (localStorage, device APIs) after the page loads.export const getFinalProps = async ({ secret, ...props }: Props) => {
// "secret" will not appear in the client bundle's JSON payload
return props;
};
export const getClientProps = async (props: PublicProps) => {
return {
...props,
theme: localStorage.getItem('theme') ?? 'dark',
};
};