The Compiler
Overviewβ
The OpenCore Compiler is the technical core of the OpenCore CLI.
It is not just a transpiler or a bundler: it is a monorepo-aware build orchestrator designed for FiveM, RageMP, RedM, and similar GTA runtimes.
Its job is to:
- Understand what each environment can and cannot do
- Compile server, client, and UI (NUI) code correctly
- Coordinate multiple resources in parallel
- Produce drop-in ready artifacts for the selected adapter/runtime
All of this is done with performance, safety, and predictability as first-class goals βοΈ
The Compiler as a Monorepo Orchestrator π§ β
An OpenCore project is effectively a monorepo of runtime units:
workspace/
ββ core/
β ββ server/
β ββ client/
β ββ views/
ββ resources/
β ββ inventory/
β β ββ server/
β β ββ client/
β β ββ views/
β ββ jobs/
β ββ chat/
ββ shared/
The compiler:
- Discovers all resources automatically
- Detects entrypoints per environment
- Builds each unit independently
- Runs them in parallel when possible
- Resolves cross-resource framework contracts (CORE β RESOURCE)
Think of it less as βtsc for FiveMβ and more as:
A coordinator that understands the topology of your server
Runtime Environmentsβ
OpenCore projects run JavaScript in three different environments. The compiler enforces hard boundaries between them and adapts output to the selected runtime.
Runtime Matrixβ
| Environment | Target | Purpose | What you can use | What will break |
|---|---|---|---|---|
| Server | Node.js | Backend logic | Node APIs, DBs, filesystem | DOM, Web APIs, GTA natives |
| Client | Neutral JS | Gameplay logic | GTA natives, runtime events | Node APIs, browser APIs |
| Views (NUI) | Browser | UI / HUD | DOM, fetch, UI frameworks | Node APIs, native APIs |
Server Environment (Node.js)β
The server runs on the runtime provided by the selected adapter.
- FiveM/RedM default to the standard resource layout used by those runtimes.
- RageMP typically targets Node 14 and uses a split layout with
packages/andclient_packages/. - Build targets are selected by adapter defaults and can be overridden in config.
Intended responsibilitiesβ
- Authentication & persistence
- Command handling
- Business logic
- External APIs
- Background jobs
Examplesβ
β Allowed
import fs from 'fs'
import crypto from 'crypto'
import pg from 'pg'
β Forbidden
window
document
GetEntityCoords(...)
The compiler:
- Targets Node explicitly
- Keeps
node_moduleswhen the adapter expects runtime resolution - Preserves Node globals
Client Environment (Neutral JS / V8)β
Client code runs inside the game client, not Node and not a browser.
This environment is intentionally minimal.
Intended responsibilitiesβ
- Player input
- Game state
- Entity interaction
- Natives and events
Examplesβ
β Allowed
onNet('event', ...)
GetEntityCoords(PlayerPedId())
Math.random()
β Forbidden
fs
process
fetch
window
require('some-lib')
The compiler:
- Bundles everything into a single file
- Strips Node & browser globals
- Fails fast on incompatible imports
This is one of the main reasons a generic bundler is not enough.
Views (NUI / Browser)β
Views run in an embedded Chromium instance.
This is browser-like, but not guaranteed to be modern Chrome. RageMP CEF is especially old, so build targets and CSS processing matter more than in a normal web app.
Intended responsibilitiesβ
- UI / HUD
- Menus
- Web-based interactions
- Styling & animations
Examplesβ
β Allowed
fetch('/api')
window.postMessage(...)
React / Vue / Svelte / other Vite-backed UI stacks
β Forbidden
fs
path
process
GTA natives
The compiler:
- Resolves views as either
viteorvanilla - Lets Vite own modern framework integration and CSS tooling
- Auto-resolves project-root PostCSS when present
- Builds optimized browser bundles and copies static assets (HTML, CSS, fonts, images)
If a project needs React, Vue, Svelte, Astro, or similar tooling, configure it in Vite rather than in the CLI.
Shared Vite configs should use @open-core/cli/vite so the CLI can resolve the view root, output directory, and PostCSS automatically.
Automatic Environment Discovery πβ
The compiler does zero-config discovery.
It scans for:
server.ts,client.ts,index.ts,main.ts- View entrypoints (
views/,ui/,nui/) - Shared root
vite.config.*or local viewvite.config.* - Resource boundaries
- Binary files (
bin/,bin/win32,bin/linux)
Diagram:
Resource
ββ server β Node build
ββ client β Neutral JS build
ββ views β Browser build
If an environment does not exist, it is simply skipped.
Adapter-Aware Output Layoutβ
The output layout depends on the selected adapter:
- FiveM/RedM: standard resource folders with
fxmanifest.lua - RageMP: split output into
packages/andclient_packages/
The compiler follows adapter metadata instead of forcing one fixed folder structure.
Technology Stackβ
The compiler is a hybrid system, each tool doing exactly what itβs best at:
- Go β orchestration, parallelism, filesystem, process control
- SWC (Rust) β TypeScript, decorators, metadata reflection
- esbuild β ultra-fast bundling and linking
- Custom plugins β adapter-specific runtime constraints and compatibility rules
This separation is deliberate:
- Go handles scale (esbuild and CLI)
- Rust handles syntax & speed (SWC)
- JS tooling handles ecosystem compatibility (embedded JS)
Parallel Build Model β‘β
Traditional builds are sequential.
OpenCore is not.
ββββββββββββββ
β Resource A ββββ
ββββββββββββββ€ ββ parallel workers β‘
β Resource B ββββ€
ββββββββββββββ€ β
β Resource C ββββ
ββββββββββββββ
Each resource:
- Is built in isolation
- Has its own dependency graph
- Does not block others
Typical results:
- 8β12 resources β < 1 second build
- CPU-bound, not IO-bound
Why this Mattersβ
The compiler guarantees that:
- Server code cannot accidentally leak into client
- Client code cannot rely on Node
- UI code stays browser-safe
- CORE and RESOURCE builds stay contract-correct
- Large projects remain maintainable and fast
For UI projects, the preferred entry point is the shared helper exported by @open-core/cli/vite.
In short:
The compiler encodes the rules of the selected runtime so you donβt have to remember them.
Final Mental Modelβ
CLI
ββ Compiler
ββ Discovers project structure
ββ Orchestrates monorepo builds
ββ Enforces runtime boundaries
ββ Runs parallel workers
ββ Emits ready-to-run resources
This is what enables OpenCore to scale from:
- a single script to
- a full modular server architecture π