Skip to content

Commit 3471c11

Browse files
authored
chore: add AGENTS.md file (#1212)
* chore: add AGENTS.md file * add file for claude
1 parent 7a795cf commit 3471c11

2 files changed

Lines changed: 209 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
# ReScript Lang Website – Agent Guidelines
2+
3+
## Project Overview
4+
5+
This is the official documentation website for the [ReScript](https://rescript-lang.org) programming language. It is a **fully pre-rendered static site** (no server-side rendering at runtime) built with **ReScript v12 + React 19 + React Router v7 + Vite 7 + Tailwind CSS v4**, deployed to **Cloudflare Pages**.
6+
7+
## System Requirements
8+
9+
- Node.js ≥ 22
10+
- Yarn 4.12.0 (via Corepack)
11+
12+
## Project Structure
13+
14+
```
15+
app/ → React Router app shell (root layout, route definitions, route modules)
16+
routes/ → Route components with loaders (e.g. BlogRoute.res, MdxRoute.res)
17+
src/ → Core ReScript source code
18+
bindings/ → Zero-cost bindings to JS libraries (@module externals)
19+
common/ → Shared utilities, hooks, helpers (non-component modules)
20+
components/ → Reusable React components
21+
ffi/ → Plain JS interop files (prefer %raw over adding new files here)
22+
layouts/ → Page layout components (DocsLayout, SidebarLayout, etc.)
23+
markdown-pages/ → MDX content (blog posts, docs, community pages, syntax-lookup)
24+
data/ → Hand-curated data (API docs JSON, sidebar ordering)
25+
styles/ → CSS files (Tailwind v4 config in main.css, custom utilities)
26+
scripts/ → Build/codegen scripts (ReScript + JS)
27+
functions/ → Cloudflare Pages Functions (e.g. OG image generation)
28+
compilers/ → Bundled ReScript compiler versions (for the playground)
29+
plugins/ → HighlightJS & CodeMirror plugins
30+
public/ → Static assets (images, fonts, favicons)
31+
__tests__/ → Vitest browser-mode tests (Playwright)
32+
```
33+
34+
## Key Commands
35+
36+
| Command | Purpose |
37+
| ---------------- | -------------------------------------------------------------- |
38+
| `yarn dev` | Run ReScript watcher + Vite dev server + Wrangler (parallel) |
39+
| `yarn build` | Full production build (ReScript → scripts → Vite/React Router) |
40+
| `yarn build:res` | ReScript compilation only |
41+
| `yarn dev:res` | ReScript watch mode only |
42+
| `yarn format` | Run Prettier + ReScript formatter |
43+
| `yarn test` | Run example and href validation scripts |
44+
| `yarn vitest` | Run Vitest browser tests with Playwright |
45+
| `make` | Build (install deps + ReScript compile + update index) |
46+
47+
## Coding Best Practices
48+
49+
- Prefer small functions with a single purpose.
50+
- Use a functional approach but don't make it too hardcore or difficult to understand.
51+
- Keep files and modules small and focused.
52+
- `.res` files must always be capitalized (PascalCase), matching ReScript module conventions.
53+
- Use the pipe-first operator (`->`) for chaining, which is idiomatic ReScript.
54+
- Resolve all warnings and treat them as errors. The project has `"error": "+8"` in `rescript.json`.
55+
56+
## ReScript Rules
57+
58+
- You use **ReScript v12** (latest). Ensure all suggestions match this version.
59+
- Ensure any produced JSX matches ReScript JSX v4 syntax (configured with `"preserve": true`).
60+
- **Never use the `Belt` or `Js` modules** — these are legacy. Use the modern `Stdlib` / core modules instead.
61+
- Always use the `JSON.t` type for JSON values.
62+
- When dealing with promises, prefer `async/await` syntax.
63+
- The project opens `WebAPI.Global` globally via compiler flags, so Web APIs are available without prefix.
64+
- Output format is ES modules with `.jsx` suffix, compiled in-source (`.jsx` files sit alongside `.res` files).
65+
- Reference the abridged documentation for clarification on how ReScript's APIs work: https://rescript-lang.org/llms/manual/llm-small.txt
66+
- If you need more information you can access the full documentation, but do this only when needed as the docs are very large: https://rescript-lang.org/llms/manual/llm-full.txt
67+
68+
### ReScript Dependencies
69+
70+
- `@rescript/react` — React bindings
71+
- `@rescript/webapi` — Web API bindings (opened globally)
72+
73+
### JS Interop Patterns
74+
75+
The project uses several patterns for JavaScript interop. Follow the existing conventions:
76+
77+
- **`@module` externals** for binding to npm packages (see `src/bindings/` for examples):
78+
```
79+
@module("react-router") external useNavigate: unit => string => unit = "useNavigate"
80+
```
81+
- **`@module` with `@react.component`** for binding to external React components:
82+
```
83+
@module("react-router") @react.component
84+
external make: (~children: React.element) => React.element = "Outlet"
85+
```
86+
- **`%raw()`** for inline JS when no clean binding is possible:
87+
```
88+
let copyToClipboard: string => bool = %raw(`function(str) { ... }`)
89+
```
90+
- **`%%raw()`** (double percent) for top-level side-effectful JS imports.
91+
- **`@scope`** for binding to object properties like `process.env`.
92+
- **`external ... = "%identity"`** for zero-cost type coercions.
93+
- Put new bindings in `src/bindings/` as a dedicated module (e.g. `Fuse.res`, `DocSearch.res`).
94+
95+
## ReScript React
96+
97+
- This project uses **React 19** and **React Router v7** (framework mode).
98+
- The site is **pre-rendered** (`ssr: false`), so loaders have access to the filesystem during build. Loaders do **not** run on a server after the build.
99+
- Route modules live in `app/routes/` and export a `loader` and a `default` component.
100+
- Route modules **require** both a `.res` and a `.resi` (interface) file for Vite HMR to work.
101+
- Only a single React component can be exposed from a module's JS output.
102+
103+
### Route Module Pattern
104+
105+
Every route follows this pattern:
106+
107+
```rescript
108+
// SomeRoute.res
109+
type loaderData = { ... }
110+
111+
let loader: ReactRouter.Loader.t<loaderData> = async ({request}) => {
112+
// filesystem access is available here (pre-render time only)
113+
let data = ...
114+
data
115+
}
116+
117+
@react.component
118+
let default = () => {
119+
let data = ReactRouter.useLoaderData()
120+
<SomeLayout> ... </SomeLayout>
121+
}
122+
```
123+
124+
With a matching interface file:
125+
126+
```rescript
127+
// SomeRoute.resi
128+
type loaderData = { ... }
129+
let loader: ReactRouter.Loader.t<loaderData>
130+
131+
@react.component
132+
let default: unit => React.element
133+
```
134+
135+
### JSX Syntax Rules
136+
137+
- `React.useState` takes a function: `let (age, setAge) = React.useState(_ => 4)`
138+
- Every expression inside an interpolated string must be of type `string`:
139+
- Wrong: `` `age = ${42}` ``
140+
- Right: `` `age = ${42->Int.toString}` ``
141+
- `type` is a keyword in ReScript. Use `type_` for JSX props: `<button type_="submit" />`
142+
- **You cannot add text as a direct child of a React component.** Everything must be a `React.element`:
143+
- Wrong: `<h1>Hello World</h1>`
144+
- Right: `<h1>{React.string("Hello World")}</h1>`
145+
- Use `React.string`, `React.int`, `React.float`, and `React.array` for primitive conversions.
146+
- Use `React.null` for rendering nothing.
147+
- Optional props use `?` syntax: `<button ?onClick>` to pass `option<handler>`.
148+
149+
## Styling
150+
151+
- **Tailwind CSS v4** configured via the Vite plugin (`@tailwindcss/vite`). There is no `tailwind.config.js`.
152+
- All Tailwind configuration is in `styles/main.css` using CSS-native `@theme` blocks.
153+
- **LightningCSS** is used as the CSS transformer.
154+
- The project defines custom design tokens in `styles/main.css`:
155+
- Custom colors: `gray-*`, `fire-*`, `sky-*`, `berry-*`, `water`, `turtle`, `orange-*`
156+
- Custom font sizes: `text-11` through `text-68`
157+
- Custom utility classes: `hl-title`, `hl-1``hl-5`, `body-lg`, `body-md`, `body-sm`, `captions`
158+
- Fonts: Inter (sans), Roboto Mono (mono)
159+
- Use existing custom utilities and design tokens. Check `styles/main.css` before creating new ones.
160+
161+
## Testing
162+
163+
- Tests use **Vitest 4** in browser mode with **Playwright** (Chromium).
164+
- Test files live in `__tests__/` and are named `ComponentName_.test.res` (compiled to `.test.jsx`).
165+
- Tests use custom ReScript bindings in `src/bindings/Vitest.res`.
166+
- Tests are visual/integration tests that render components and assert visibility, interactions, and screenshots.
167+
- Test pattern:
168+
169+
```rescript
170+
open Vitest
171+
172+
test("description", async () => {
173+
await viewport(1440, 500)
174+
let screen = await render(<MyComponent />)
175+
let el = await screen->getByTestId("my-element")
176+
await element(el)->toBeVisible
177+
await element(el)->toMatchScreenshot("screenshot-name")
178+
})
179+
```
180+
181+
- Components requiring React Router context must be wrapped in `<BrowserRouter>`.
182+
- Run tests with `yarn vitest`.
183+
184+
## MDX Content
185+
186+
- Documentation content is in `markdown-pages/` organized by section (blog, docs, community, syntax-lookup).
187+
- MDX is processed by `react-router-mdx` with remark/rehype plugins.
188+
- Custom MDX components are mapped in `app/routes/MdxRoute.res` (e.g. `<Info>`, `<Warn>`, `<CodeTab>`, `<Video>`).
189+
- Code examples in markdown use ` ```res example ` (runnable), ` ```res sig ` (signature), and ` ```res prelude ` (shared context).
190+
191+
## Formatting & Git Hooks
192+
193+
- **Prettier** with the `@prettier/plugin-oxc` parser for JS formatting.
194+
- **ReScript formatter** (`rescript format`) for `.res` files.
195+
- **Lefthook** runs `yarn format` on pre-commit (auto-stages fixed files).
196+
- Generated `.mjs`/`.jsx` output files from ReScript are git-tracked but excluded from Prettier.
197+
198+
## Important Warnings
199+
200+
- Do **not** modify generated `.jsx` / `.mjs` files directly — they are ReScript compiler output.
201+
- Do **not** use `@genType` — the project does not use it.
202+
- The `src/ffi/` directory is legacy; prefer `%raw` statements for new JS interop.
203+
- The README references some outdated structures (Next.js, `pages/` directory) — ignore those references. The project has migrated to React Router v7.
204+
- When editing route files, always update both the `.res` and `.resi` files.

CLAUDE.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Claude Code Guidelines
2+
3+
All project guidelines, coding conventions, and agent instructions are maintained in a single shared file.
4+
5+
See @AGENTS.md for the full reference.

0 commit comments

Comments
 (0)