A production-ready template for building modern web applications with ReScript, Rspack, React 19, Relay, and Emotion CSS-in-JS. Editorial design with Playfair Display serif typography.
| Layer | Technology |
|---|---|
| Language | ReScript 12.2 |
| UI | React 19.2 |
| Bundler | Rspack 1.7 |
| Styling | Emotion CSS-in-JS |
| Data | Relay (rescript-relay) + GraphQL |
| Auth | OAuth 2.0 PKCE |
| Testing | Vitest + React Testing Library |
| Route | Description |
|---|---|
/ |
Editorial homepage with stack overview |
/components |
Component library showcase |
/posts |
Blog posts fetched via Relay (protected, requires auth) |
/login |
OAuth 2.0 PKCE sign-in |
- Bun installed locally
curl -fsSL https://bun.sh/install | bashbun install
bun run devThis starts three processes concurrently:
- ReScript watcher (compiles
.resto.bs.js) - Rspack dev server at
http://localhost:8080 - Mock GraphQL server at
http://localhost:4000/graphql
| Script | Description |
|---|---|
bun run dev |
Start all dev services |
bun run dev:server |
Start mock GraphQL/OAuth server only |
bun run build |
Production build |
bun run res:build |
Compile ReScript |
bun run res:dev |
ReScript watch mode |
bun run res:clean |
Clean ReScript build |
bun run relay |
Run Relay compiler |
bun run test |
Run tests |
bun run test:watch |
Run tests in watch mode |
bun run lint |
Lint with Biome |
bun run format:write |
Format with Biome |
bun run commit |
Create conventional commit |
.resfiles compile to.bs.jsES modules (in-source)- Rspack bundles the
.bs.jsfiles with React Fast Refresh .bs.jsfiles are gitignored build artifacts
src/
pages/ # Route pages (Home, Components, Posts, Login)
components/ # UI components (Button, Card, Input, Typography, ...)
styles/ # Design system (Theme, GlobalStyles, Layout)
bindings/ # JS library bindings (Emotion, OAuthPkce)
context/ # React contexts (AuthContext)
relay/ # Relay environment
__tests__/ # Vitest test suites
__generated__/ # Relay compiler output
mock-server/ # GraphQL + OAuth mock server
Tokens are centralized in src/styles/Theme.res. Components reference tokens via Emotion.Utils.Color rather than hardcoded values. Changing a color in Theme.res propagates everywhere.
OAuth 2.0 Authorization Code + PKCE flow:
- User clicks "Sign in with OAuth" on
/login - Browser redirects to mock server's
/oauth/authorize - Mock server auto-approves, redirects to
/callback?code=...&state=... CallbackPagevalidates state, exchanges code for token- User is authenticated and can access
/posts
Posts are fetched via Relay using a %relay query that compiles at build time. The mock GraphQL server provides User and Post types with in-memory data.
module PostsQuery = %relay(`
query PostsPageQuery {
posts {
id
title
body
author { name }
}
}
`)- Button — 5 variants, 5 sizes, loading state, icon support
- Input — 4 variants, 3 sizes, 4 validation states
- Card — 3 variants with Header/Body/Footer
- Typography — Display, Heading, Body, Caption, Overline
- Avatar — Initials fallback, 3 sizes
- Badge — 5 semantic variants
- Blockquote — Serif italic with attribution
- Divider — Horizontal rule with optional label
- Biome for linting and formatting
- Husky pre-commit hooks (format + lint)
- Commitizen with commitlint for conventional commits
- Vitest with React Testing Library (18 tests)
Deployed via Vercel. The Posts and Login pages require the mock server running locally.


