Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 130 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,150 @@
Rspack & Rescript with Bun
# Rspack + ReScript Template

## Features
- `commitizen`
- `commitlint`
- `biome.js`
- `husky`
- `release-please` (future)
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.

## How to get started
![Home page](docs/screenshots/home.png)

Ensure you have `bun` installed on your local machine.
## Stack

| 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 |

## Pages

| 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 |

![Components page](docs/screenshots/components.png)

## Getting started

### Prerequisites

- [Bun](https://bun.sh) installed locally

```bash
curl -fsSL https://bun.sh/install | bash
```

Run `bun install` to install dependencies.

To build `.res` files
### Install and run

```bash
bun run res:build
bun install
bun run dev
```

To build for production with `rspack`
This starts three processes concurrently:

```bash
bun run build
- **ReScript** watcher (compiles `.res` to `.bs.js`)
- **Rspack** dev server at `http://localhost:8080`
- **Mock GraphQL server** at `http://localhost:4000/graphql`

### Scripts

| 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 |

## Architecture

### ReScript compilation flow

1. `.res` files compile to `.bs.js` ES modules (in-source)
2. Rspack bundles the `.bs.js` files with React Fast Refresh
3. `.bs.js` files are gitignored build artifacts

### Project structure

```
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
```

To test your local changes, run `bun run res:build` to build the `.res` files
### Design system

And then
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.

```bash
bun run res:dev
### Authentication

OAuth 2.0 Authorization Code + PKCE flow:

1. User clicks "Sign in with OAuth" on `/login`
2. Browser redirects to mock server's `/oauth/authorize`
3. Mock server auto-approves, redirects to `/callback?code=...&state=...`
4. `CallbackPage` validates state, exchanges code for token
5. User is authenticated and can access `/posts`

![Sign in page](docs/screenshots/posts.png)

### Data fetching

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.

```rescript
module PostsQuery = %relay(`
query PostsPageQuery {
posts {
id
title
body
author { name }
}
}
`)
```

in order to see your local changes at `http://localhost:8080`
## Component library

- **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

## Code quality

- **Biome** for linting and formatting
- **Husky** pre-commit hooks (format + lint)
- **Commitizen** with commitlint for conventional commits
- **Vitest** with React Testing Library (18 tests)

## Deployment

Deployed via [Vercel](https://vercel.com). The Posts and Login pages require the mock server running locally.

## License

This app is also deployed via Vercel.sh.
[MIT](LICENSE)
Binary file added docs/screenshots/components.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/home.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/login.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/posts.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.