Comprehensive Web-Based OCaml IDE (React Frontend + Express Backend) featuring code execution, memory visualization, project sharing, and Learn OCaml integration.
- Features
- Technical Stack
- Prerequisites
- Installation
- Running the Project
- Environment Variables
- Project Structure
- Core API
- Keyboard Shortcuts
- Important Notes
- 🔐 User Authentication: Secure registration and login via JWT.
- 📂 Project Management: Create, edit, and delete multi-file OCaml projects.
- 🎨 Monaco Editor IDE: Syntax highlighting, code snippets, auto-completion, and type hovering.
- ⚡ Robust OCaml Execution:
- Native Backend Mode: Uses the system
ocamlbinary (if available). - Browser Fallback: Seamlessly switches to an embedded in-browser OCaml interpreter if server tools are missing.
- Native Backend Mode: Uses the system
- 🛠️ Optional Tool Integration:
ocamlmerlinfor advanced completion, type inference, and error reporting.ocamlformatfor automated code formatting.
- 🧠 Memory Visualization: Real-time inspection of the environment, stack, heap, and data types.
- 🔗 Social Sharing: Public project sharing via unique links with forking capabilities.
- 🎓 Learn OCaml Integration: Connect to instances, browse exercises, synchronize answers, and view grading reports (fully supports client-side grading via sandboxed Web Workers).
- Framework: React 18 + TypeScript
- Build Tool: Vite 5
- State Management: Zustand
- Editor: Monaco Editor
- Styling: Tailwind CSS
- Routing: React Router
- Runtime: Node.js + Express
- Database: SQLite (
better-sqlite3) - Security: JWT (
jsonwebtoken) & Password Hashing (bcryptjs)
- Node.js 18+ (Recommended)
- npm
- Optional (For the full OCaml experience):
ocamlocamlmerlinocamlformatopam
⚠️ Important: Server-side detection of OCaml tools is cross-platform (Windows, macOS, Linux). If these tools are not installed, the application will gracefully degrade and remain fully functional using the browser-based fallback engine without generating system errors.
Navigate to the Caraml/ directory:
npm install
To ensure portability and reduce repository size, binary files (ocaml, ocamlmerlin, ocamlformat) are not versioned in Git. Instead, the project provides a reproducible installation script via opam.
For Windows Users (requires winget):
winget install Git.Git OCaml.opam
Run the setup script:
npm run setup:ocaml
This script creates (or reuses) a local switch in ./_opam and installs:
ocaml-base-compiler.5.4.0merlin.5.6.1-504ocamlformat.0.28.1
Script Behavior:
- If
opamis present but uninitialized, the script automatically executesopam init(using--cygwin-internal-installon Windows to bypass interactive prompts). - During long-running processes (such as OCaml compilation), the script displays a periodic
still running (...)heartbeat.
Auto-Bootstrap System:
Subsequently, npm run dev automatically detects these tools. It also performs an auto-bootstrap check (ensure:ocaml) on startup:
- If the toolchain is missing and
opamis available, it automatically triggerssetup:ocaml. - On Windows, if
opamis missing, it attempts installation viawinget, followed by the official opam script (best-effort). - If installation fails, the application starts in Browser Fallback Mode.
To disable auto-bootstrap:
npm run dev:no-ocaml
Or via environment variables/options:
CARAML_SKIP_OCAML_AUTO_SETUP=1 npm run dev
# OR
npm run dev -- --skip-ocaml
PowerShell:
$env:CARAML_SKIP_OCAML_AUTO_SETUP="1"; npm run dev
If you do not have opam installed, refer to the official documentation: Install OCaml
npm run dev
- Frontend:
http://localhost:5173 - Backend API:
http://localhost:3001(Incremented automatically if port 3001 is busy) - The frontend automatically proxies
/apirequests to the backend. - Graceful Degradation: If
ocaml,ocamlmerlin, orocamlformatare unavailable, the server cleanly switches to fallback mode, disabling backend-specific features.
npm run dev:client
npm run dev:server
npm run build
npm run start
Note:
npm run startserves the contents of thedist/directory via Express. Ensure you executenpm run buildprior to starting.
The following variables can be configured:
JWT_SECRET(Required in production): Secret used to sign session tokens. If unset in production, an ephemeral secret is generated at startup (all sessions are invalidated on restart) and a warning is logged.CARAML_API_PORT/PORT(Optional): Backend port (default3001).CARAML_ALLOWED_ORIGINS(Optional): Comma-separated list of additional origins allowed by CORS (localhost origins are allowed by default).CARAML_OCAML_PATH(Optional): Explicit path to theocamlbinary.CARAML_OCAMLMERLIN_PATH(Optional): Explicit path to theocamlmerlinbinary.CARAML_OCAMLFORMAT_PATH(Optional): Explicit path to theocamlformatbinary.
Bash Example:
JWT_SECRET="change-me" \
CARAML_OCAML_PATH="/usr/local/bin/ocaml" \
CARAML_OCAMLMERLIN_PATH="/usr/local/bin/ocamlmerlin" \
CARAML_OCAMLFORMAT_PATH="/usr/local/bin/ocamlformat" \
npm run dev:server
PowerShell Example:
$env:JWT_SECRET="change-me"
$env:CARAML_OCAML_PATH="C:\\Tools\\OCaml\\bin\\ocaml.exe"
$env:CARAML_OCAMLMERLIN_PATH="C:\\Tools\\OCaml\\bin\\ocamlmerlin.exe"
$env:CARAML_OCAMLFORMAT_PATH="C:\\Tools\\OCaml\\bin\\ocamlformat.exe"
npm run dev:server
Note: The backend listens on 3001 by default; override it with CARAML_API_PORT or PORT.
Caraml/
|-- src/
| |-- components/ # UI Components (Header, Editor, Console, Modals...)
| |-- pages/ # Dashboard, IDE, Share, Learn OCaml
| |-- services/ # Frontend API Clients
| |-- store/ # Global Zustand Store
| `-- interpreter/ # Browser-based OCaml Interpreter (Fallback)
|-- server.js # Express API + SQLite + OCaml Tooling
|-- package.json
|-- tailwind.config.js
`-- vite.config.ts
Local SQLite Database Files:
caraml.dbcaraml.db-shmcaraml.db-wal
POST /api/auth/registerPOST /api/auth/loginGET /api/auth/me
GET /api/projectsPOST /api/projectsGET /api/projects/:idPUT /api/projects/:idDELETE /api/projects/:id
POST /api/projects/:id/sharePOST /api/projects/:id/unshareGET /api/shared/:shareIdPOST /api/shared/:shareId/fork
GET /api/capabilitiesPOST /api/executePOST /api/toplevelPOST /api/formatPOST /api/merlin/completePOST /api/merlin/typePOST /api/merlin/errors
POST /api/learn-ocaml/connectPOST /api/learn-ocaml/exercisesPOST /api/learn-ocaml/exercise/*POST /api/learn-ocaml/savePOST /api/learn-ocaml/sync-answerPOST /api/learn-ocaml/sync-gradePOST /api/learn-ocaml/grade(fallback)POST /api/learn-ocaml/grader-workerPOST /api/learn-ocaml/exercise-raw/*
Ctrl+Enter: Run codeCtrl+S: Save projectCtrl+Shift+F: Format code (requiresocamlformat)
Ctrl+Enter: Run codeCtrl+S: Sync answerCtrl+Shift+G: Submit for grading
- System Fallback: If the
ocamlbinary is not detected, the application remains fully operational via the browser interpreter to prevent system errors. - Merlin Availability: If
ocamlmerlinis missing, the editor reverts to local Monaco-based autocompletion. - Formatting: If
ocamlformatis missing, the "Format" button is disabled. - Security: The default JWT secret located in
server.jsmust be replaced with a secure environment variable for any real-world deployment.