Who this is for: developers new to the monorepo who want to run Rocket.Chat from source for the first time.
After reading this you will have: the app running at
http://localhost:3000, logged in as an admin user, ready to edit code with hot
reload.
Goal: clone → app running in under ~30 min (excluding download time).
| Tool | Version pinned in | How to get it |
|---|---|---|
| Node.js | package.json → volta.node (engines.node is the accepted range) |
Volta picks it automatically, or fnm/nvm install <version> |
| Yarn | package.json → packageManager |
Ships via Corepack: corepack enable |
| Meteor | apps/meteor/.meteor/release |
the installer |
| Git | any recent | — |
Building from source needs 16 GB of RAM or more. Use exactly the pinned versions — mismatches cause obscure build errors.
Check everything at once; the script reads the pins from the repo:
./scripts/check-deps.sh # report what is missing or on the wrong version
./scripts/check-deps.sh --install # install what it canMongoDB is not required for the first run: Meteor starts a bundled Mongo, which already runs as a single-node replica set — enough for the transactions and change streams the app relies on. You only need an external Mongo to mirror production or to inspect data with an external client (see section 5).
git clone https://github.com/RocketChat/Rocket.Chat.git
cd Rocket.Chat
./scripts/check-deps.sh --install # Node, Yarn and Meteor at the pinned versions
yarn # installs all workspaces (slow the first time)
yarn build # builds the workspace packages that have a build stepThis is a monorepo (Yarn workspaces + Turborepo). Running yarn at the root
installs apps/*, packages/* and ee/* at once. Do not run yarn inside
subfolders.
Installed files are hard links into Yarn's global store (nmMode: hardlinks-global), so every clone and
worktree on the machine shares one copy of each package. Editing a file under node_modules edits it for
all of them: change a dependency with yarn patch instead.
The Meteor app loads the other workspace packages from their dist folders, so
yarn build must finish before the first start. Run it again after a pull that
changes packages.
Do not run
yarn devfrom the root. It starts atsc --watchfor every package the app depends on, which costs a lot of CPU, and it does not build the packages that have nodevscript — on a fresh clone the app fails to start.
Run yarn dev inside the workspace you work in. For the Meteor app:
cd apps/meteor
yarn devOnce you see the server listening, open:
http://localhost:3000
On the first run the Setup Wizard asks you to create the admin user and the organization. That's it — you are running.
yarn dev runs the Rocket.Chat server and the web client together:
- It builds the packages the app depends on (
turbo run build --filter=@rocket.chat/meteor^...). If the build fails, nothing starts. - It starts the Meteor server on
METEOR_PORT(default3100).ROOT_URLdefaults to the client address, so the links that the server builds (emails, OAuth callbacks) point to it. - It starts Vite on
PORT(default3000). Vite serves the page the server renders, as in production, with the client from your working tree in it, and sends the server routes (/api,/websocket,/sockjs,/_oauth,/avatar,/file-uploadand others) to Meteor.
Client edits hot-reload in the browser. Server edits make Meteor restart. Ctrl+C stops Vite, Meteor and the bundled Mongo together.
The first Meteor compilation is slow (several minutes). Subsequent ones use the cache and are much faster.
Set RC_SERVER_URL to a Rocket.Chat server that already runs. Only Vite
starts: no Meteor compilation and no Mongo. The script builds only the packages
that the client reads from dist, so this is the fastest way to start on
client work.
You log in with an account on the remote server, and every action changes the data on that server. Do not point
RC_SERVER_URLat a production workspace.
cd apps/meteor
RC_SERVER_URL=https://my-server.example.com yarn devVite rewrites the cookies of the server to the local address, so the login and
the file downloads work. The page is Vite's own index.html, not the one the
server renders, so the server's head injections (title, theme variables,
custom scripts) are missing.
The client runs your code, but the server runs its own version. A client change
that needs a server change from your branch does not work in this mode — run
yarn dev without RC_SERVER_URL for it.
The client compiles most workspace packages in packages/ and ee/packages/
from their source. An edit to one of these packages hot-reloads in the browser,
with no yarn dev in the package. These rules apply:
-
The client reads a few packages from
dist, because their build does more than compile TypeScript. The list is inapps/meteor/vite/workspacePackages.mjs. After you edit one of them, runyarn buildin that package. -
The Meteor server loads every package from
dist. For a change that the server uses, runyarn dev(tsc --watch) in that package, in a separate terminal:cd packages/rest-typings yarn devMeteor picks up the new
diston its next reload. For a one-shot rebuild, or in a package without adevscript (fuselage,ui-kit,message-parserand others), runyarn buildin that package instead. -
Set
RC_WORKSPACE_DIST=1to make the client read every package fromdist.
In production the server serves the client itself: yarn build:client builds
it into public/bundle, and yarn build:ci runs it before meteor build. See
features/web-client-hosting.md for how the
server loads it and how to serve the client from another host.
Rocket.Chat is configured through environment variables. All are optional for the first run — with none set, the app boots on the bundled Mongo. A var exported in your shell is picked up on the next start. The most used ones:
| Var | Purpose |
|---|---|
PORT |
HTTP port (default 3000) |
ROOT_URL |
public URL; must match how you open it in the browser |
MONGO_URL |
point at an external Mongo instead of the bundled one (see section 5) |
ROCKETCHAT_LICENSE |
enables Enterprise (EE) features |
The bundled Mongo already covers local dev. Set up an external one only to mirror production or to point external tooling at the data.
Rocket.Chat needs a replica set — not for the oplog (Meteor oplog tailing is disabled; real-time is handled by the streamer), but because transactions and change streams require it. A single-node replica set is enough:
docker run -d --name rc-mongo -p 27017:27017 \
mongodb/mongodb-community-server:8.0-ubi8 \
mongod --replSet rs0 --bind_ip_all
until docker exec rc-mongo mongosh --quiet --eval "db.adminCommand('ping')" >/dev/null 2>&1; do sleep 1; done
docker exec rc-mongo mongosh --eval "rs.initiate()"Then point the app at it by exporting in your shell before yarn dev
(Meteor does not load a .env file):
export MONGO_URL='mongodb://localhost:27017/rocketchat?replicaSet=rs0'| Command | What it does | When to use |
|---|---|---|
yarn dev (in apps/meteor) |
Meteor server + Vite client | default — day-to-day development |
RC_SERVER_URL=<url> yarn dev (in apps/meteor) |
Vite client against a remote server | client work without a local server |
yarn ms |
Microservices mode (transporter, default TCP) | working on services (presence, ddp-streamer, authorization…) |
yarn storybook |
Component Storybook on port 6006 | developing UI in isolation |
yarn build |
Full monorepo build (Turbo) | validate build / local CI |
Command (in apps/meteor) |
Type |
|---|---|
yarn testunit |
unit (definition + jest + mocha server, with coverage) |
yarn testapi |
API tests (mocha, needs a running server) |
yarn test:e2e |
end-to-end (Playwright) |
yarn lint |
stylelint + oxlint |
yarn typecheck |
meteor lint + tsc --noEmit |
From the root, yarn testunit and yarn lint run via Turbo across all
workspaces.
See local-dev/troubleshooting.md — Watchman, file watching, processes that won't die, Mongo, ports.
If you get stuck on something not documented there: open an issue with the
docs label (or a short PR fixing this guide). That's the mechanism — every
new-dev blocker becomes a doc improvement.