diff --git a/.oxfmtrc.json b/.oxfmtrc.json index 85a79c701..1bb91247a 100644 --- a/.oxfmtrc.json +++ b/.oxfmtrc.json @@ -37,6 +37,6 @@ "apps/docs/public/llms/react/**/llm*.txt", "apps/docs/markdown-pages/docs/**/**/llms.mdx", "apps/docs/markdown-pages/docs/manual/installation.mdx", - ".yarn/releases/yarn-4.12.0.cjs" + ".yarn/releases/*.cjs" ] } diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 241f2c935..9cf683216 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,3 +1,3 @@ { - "recommendations": ["esbenp.prettier-vscode", "chenglou92.rescript-vscode"] + "recommendations": ["oxc.oxc-vscode", "chenglou92.rescript-vscode"] } diff --git a/AGENTS.md b/AGENTS.md index 20a6c4e85..cbf94c8d9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,47 +2,64 @@ ## Project Overview -This is the official documentation website for the [ReScript](https://rescript-lang.org) programming language. It is primarily pre-rendered at build time, with runtime server-side rendering for `/try` through Cloudflare Pages Functions. It is built with **ReScript v12 + React 19 + React Router v8 + Vite 8 + Tailwind CSS v4**, deployed to **Cloudflare Pages**. +This monorepo contains the official documentation website for the [ReScript](https://rescript-lang.org) programming language and the interactive guide. Both use **ReScript v12 + React 19 + React Router v8 + Vite 8**. The docs site uses Tailwind CSS v4 and is primarily pre-rendered at build time, with runtime server-side rendering for `/try` through Cloudflare Pages Functions. The guide pre-renders its entry page and runs its interactive lessons in the browser, with assets served by a Cloudflare Worker. ## System Requirements - Node.js ≥ 26 -- Yarn 4.12.0 (via Corepack) +- Yarn 4.13.0 (via Corepack, pinned in `package.json` and `.yarnrc.yml`) ## Project Structure ``` -app/ → React Router app shell (root layout, route definitions, route modules) - routes/ → Route components with loaders (e.g. BlogRoute.res, MdxRoute.res) -src/ → Core ReScript source code - bindings/ → Zero-cost bindings to JS libraries (@module externals) - common/ → Shared utilities, hooks, helpers (non-component modules) - components/ → Reusable React components (e.g. SidebarNav, Breadcrumbs) - ffi/ → Plain JS interop files (prefer %raw over adding new files here) - layouts/ → Page layout components (DocsLayout, SidebarPageLayout, etc.) -markdown-pages/ → MDX content (blog posts, docs, community pages, syntax-lookup) -data/ → Hand-curated data (API docs JSON, sidebar ordering) -styles/ → CSS files (Tailwind v4 config in main.css, custom utilities) -scripts/ → Build/codegen scripts (ReScript + JS) -functions/ → Cloudflare Pages Functions (e.g. OG image generation) -compilers/ → Bundled ReScript compiler versions (for the playground) -plugins/ → HighlightJS & CodeMirror plugins -public/ → Static assets (images, fonts, favicons) -__tests__/ → Vitest browser-mode tests (Playwright) +apps/docs/ → Documentation website workspace (@rescript-lang/docs) + app/ → React Router shell, layouts, and route modules + routes/ → Page components and loaders (e.g. BlogRoute.res) + src/ → Website ReScript code + bindings/ → App-specific bindings to JS libraries + common/ → Shared website utilities and hooks + components/ → Reusable React components + ffi/ → Legacy plain JS interop + layouts/ → Page layout components + markdown/ → MDX loading, compilation, and frontmatter parsing + markdown-pages/ → Blog, docs, community, and syntax-lookup MDX + data/ → Sidebar ordering and content metadata + styles/ → Tailwind v4 entry points, theme, and custom CSS + scripts/ → Build, code generation, and validation scripts + functions/ → Pages Functions for /try, /try.data, and OG images + server/ → React Router request handler for Pages Functions + public/ → Static assets (images, fonts, favicons) + __tests__/ → Vitest browser and visual tests + e2e/ → Cypress browser tests +apps/guide/ → Interactive guide workspace (@rescript-lang/guide) +packages/playground/ → Shared browser playground (@rescript-lang/playground) +packages/shared/ → Shared bindings and utilities (@rescript-lang/shared) + src/ → ReactRouter, Vitest, CodeMirror, highlighting, etc. + plugins/ → CodeMirror 6 ReScript/Reason grammar +data/api/ → Compiler-published API JSON snapshots +.github/ → CI, deployment, and screenshot workflows ``` +Paths in these guidelines are relative to the repository root. Run the commands +below from there; use `yarn workspace ` for workspace commands. +The playground loads published browser compiler bundles. Markdown example checks +use the installed `rescript` package, not a separate compiler installation. + ## Key Commands -| Command | Purpose | -| ---------------- | -------------------------------------------------------------- | -| `yarn dev` | Run ReScript watcher + Vite dev server + Wrangler (parallel) | -| `yarn build` | Full production build (ReScript → scripts → Vite/React Router) | -| `yarn build:res` | ReScript compilation only | -| `yarn dev:res` | ReScript watch mode only | -| `yarn format` | Run Prettier + ReScript formatter | -| `yarn test` | Run example and href validation scripts | -| `yarn vitest` | Run Vitest browser tests with Playwright | -| `make` | Build (install deps + ReScript compile + update index) | +| Command | Purpose | +| ------------------- | ------------------------------------------------------------ | +| `yarn dev` | Run ReScript watcher + Vite dev server + Wrangler (parallel) | +| `yarn build` | Build and pre-render the docs site | +| `yarn build:guide` | Build and pre-render the interactive guide | +| `yarn build:res` | Compile ReScript across all four workspaces | +| `yarn dev:res` | ReScript watch mode only | +| `yarn format` | Run Oxfmt and format ReScript across all four workspaces | +| `yarn test` | Run example, href, and redirect validation scripts | +| `yarn vitest` | Run docs Vitest browser tests in watch mode | +| `yarn vitest:guide` | Run guide Vitest browser tests in watch mode | +| `yarn ci:test` | Run docs and guide Vitest browser tests headlessly | +| `make` | Build (install deps + ReScript compile + update index) | ## Coding Best Practices @@ -52,11 +69,11 @@ __tests__/ → Vitest browser-mode tests (Playwright) - `.res` files must always be capitalized (PascalCase), matching ReScript module conventions. - Use the pipe-first operator (`->`) for chaining, which is idiomatic ReScript. - Resolve all warnings and treat them as errors. The project has `"error": "+8"` in `rescript.json`. -- Never directly edit an `.jsx` files, you must edit the corresponding `.res` file. The `.jsx` files are generated by the ReScript compiler and will be overwritten on the next compile. +- Never directly edit generated `.jsx` files; edit the corresponding `.res` file and rebuild. Most compiler output is ignored by Git; the guide's `apps/guide/app/root.jsx` and `apps/guide/app/routes.jsx` are tracked and must be regenerated with their sources. ## ReScript Rules -- You use **ReScript v12** (latest). Ensure all suggestions match this version. +- This branch uses **ReScript v12**. Ensure all suggestions match this version. - Ensure any produced JSX matches ReScript JSX v4 syntax (configured with `"preserve": true`). - **Never use the `Belt` or `Js` modules** — these are legacy. Use the modern `Stdlib` / core modules instead. - Always use the `JSON.t` type for JSON values. @@ -78,7 +95,7 @@ __tests__/ → Vitest browser-mode tests (Playwright) The project uses several patterns for JavaScript interop. Follow the existing conventions: -- **`@module` externals** for binding to npm packages (see `src/bindings/` for examples): +- **`@module` externals** for binding to npm packages (see `apps/docs/src/bindings/` and `packages/shared/src/` for examples): ``` @module("react-router") external useNavigate: unit => string => unit = "useNavigate" ``` @@ -87,21 +104,17 @@ The project uses several patterns for JavaScript interop. Follow the existing co @module("react-router") @react.component external make: (~children: React.element) => React.element = "Outlet" ``` -- **`%raw()`** for inline JS when no clean binding is possible: - ``` - let copyToClipboard: string => bool = %raw(`function(str) { ... }`) - ``` -- **`%%raw()`** (double percent) for top-level side-effectful JS imports. +- `%raw` and `%%raw` embed JavaScript; use them only when specifically requested. - **`@scope`** for binding to object properties like `process.env`. - **`external ... = "%identity"`** for zero-cost type coercions. -- Put new bindings in `src/bindings/` as a dedicated module (e.g. `Fuse.res`, `DocSearch.res`). +- Put app-specific bindings in `apps/docs/src/bindings/` as a dedicated module (e.g. `Fuse.res`, `DocSearch.res`). Bindings shared with the guide or playground belong in `packages/shared/src/`. ## ReScript React - This project uses **React 19** and **React Router v8** (framework mode). - The site uses hybrid rendering: most routes are pre-rendered during the build, while `/try` is server-rendered by Cloudflare Pages Functions at runtime. - Loaders for pre-rendered routes can access the filesystem during the build. Runtime SSR loaders, including shared loader code reachable from `/try`, execute in Cloudflare and must not depend on Node-only filesystem APIs or other build-time-only operations. -- Route modules live in `app/routes/` and export a `loader` and a `default` component. +- Docs route modules live in `apps/docs/app/routes/`; the guide's route modules live in `apps/guide/app/`. Routes can export a `loader`, `links`, and a `default` component as needed. - Route modules **require** both a `.res` and a `.resi` (interface) file for Vite HMR to work. - Only a single React component can be exposed from a module's JS output. @@ -153,21 +166,21 @@ let default: unit => React.element ## Styling -- **Tailwind CSS v4** configured via the Vite plugin (`@tailwindcss/vite`). There is no `tailwind.config.js`. -- Tailwind design tokens and custom utilities live in `styles/_theme.css`. It is imported by `styles/main.css` and referenced by route-specific stylesheets. +- The docs site uses **Tailwind CSS v4**, configured via the Vite plugin (`@tailwindcss/vite`). Design tokens and custom utilities live in `apps/docs/styles/_theme.css`, imported by `apps/docs/styles/main.css` and referenced by route-specific stylesheets. +- The guide uses its own plain CSS in `apps/guide/styles/main.css`. - **LightningCSS** is used as the CSS transformer. -- The project defines custom design tokens in `styles/_theme.css`: +- The project defines custom design tokens in `apps/docs/styles/_theme.css`: - Custom colors: `gray-*`, `fire-*`, `sky-*`, `berry-*`, `water`, `turtle`, `orange-*` - Custom font sizes: `text-11` through `text-68` - Custom utility classes: `hl-title`, `hl-1`–`hl-5`, `body-lg`, `body-md`, `body-sm`, `captions` - Fonts: Inter (sans), Roboto Mono (mono) -- Use existing custom utilities and design tokens. Check `styles/_theme.css` before creating new ones. +- Use existing custom utilities and design tokens. Check `apps/docs/styles/_theme.css` before creating new ones. ## Testing - Tests use **Vitest 5** in browser mode with **Playwright** (Chromium). -- Test files live in `__tests__/` and are named `ComponentName_.test.res` (compiled to `.test.jsx`). -- Tests use custom ReScript bindings in `src/bindings/Vitest.res`. +- Browser tests live in `apps/docs/__tests__/` and `apps/guide/__tests__/`. Docs visual tests live in `apps/docs/__tests__/visual/`. Test modules are named `ComponentName_.test.res` (compiled to `.test.jsx`). +- Tests use custom ReScript bindings in `packages/shared/src/Vitest.res`. - Tests are visual/integration tests that render components and assert visibility, interactions, and screenshots. - Test pattern: @@ -185,22 +198,25 @@ let default: unit => React.element - Components requiring React Router context must be wrapped in ``. - Do not use `` in tests. -- Run tests with `yarn vitest --browser.headless --run`. -- Do not update snapshots without asking for confirmation. +- Run `yarn build:res` first so the tests use current compiler output. Run `yarn vitest --browser.headless --run` for docs tests or `yarn vitest:guide --browser.headless --run` for guide tests. Run `yarn ci:test` to check both suites. +- Do not update snapshots without asking for confirmation. Approved docs visual baseline changes use the `Update Visual Regression Screenshots` GitHub Actions workflow against the feature branch; pull and review the generated commit. Local screenshot updates are blocked by the Vitest configuration. ## MDX Content -- Documentation content is in `markdown-pages/` organized by section (blog, docs, community, syntax-lookup). -- MDX is processed by `react-router-mdx` with remark/rehype plugins. -- Custom MDX components are mapped in `app/routes/MdxRoute.res` (e.g. ``, ``, ``, `