Ready-to-use Node.js backend framework. One process serves a JSON API, Socket.IO, cron jobs, and an in-process queue on a clean four-layer architecture (config → core → app) with centralized configuration.
npm create rebe@latest my-api
cd my-api
npm install
npm run devFlags (all optional): --name <name>, --pm <npm|pnpm|yarn|bun>, --install,
--git, --no-env, --force, -y. Unless --no-env is set, a .env is generated
with APP_NAME set to the project name and fresh APP_KEY / JWT secrets.
- HTTP — Express 5 + a built-in Laravel-style router (
@core/routing.core), helmet, CORS, compression, rate limiting, body limits, multipart uploads. - Realtime — Socket.IO on the same port, optional Redis adapter.
- Background — node-cron scheduler and an in-process job queue (optional DB persistence).
- Data — Sequelize (MySQL/MariaDB/Postgres/MSSQL/SQLite), enabled on demand, with a built-in migration runner, seeders, and a generator CLI.
- Auth — JWT (access + refresh, HS256-pinned), bcrypt.
- Ops — Winston logging with daily rotation, lifecycle hooks, graceful shutdown, PM2 config.
- Optional Redis — standalone; each feature opts in and falls back cleanly.
npm install
npm run cli -- setup # copy .env, install deps, generate keys
npm run dev # nodemon, developmentsetup copies .env.example to .env, installs the pinned dependencies, and
generates APP_KEY, JWT_SECRET, and JWT_REFRESH_SECRET. Pass --upgrade to also
bump dependencies via npm-check-updates (off by default, so a clean install stays on
the audited versions). Generate keys individually with npm run cli -- key:generate
and npm run cli -- key:jwt [--refresh].
| Development | Production | |
|---|---|---|
| Start | npm run dev (nodemon) |
npm start (node .) or PM2 |
APP_ENV |
development |
production |
| Logs | colored console + rotating files | console filtered, rotating files in logs/ |
| Error responses | include stack | stack hidden |
Production with PM2 (single fork instance):
pm2 start ecosystem.config.js
pm2 logs <APP_NAME>Run a single instance (
exec_mode: 'fork', instances: 1). State is kept in-process (Socket.IO rooms, the in-process queue, node-cron schedules). Cluster mode would duplicate cron ticks, split socket rooms, and break queue state. For horizontal scale, enable Redis (REDIS_USE_SOCKET/REDIS_USE_QUEUE) first.
Four layers with a strict, one-directional dependency arrow:
Entry (index.js -> bootstrap.core)
-> Application (app/: http, routes, jobs, queue, socket, hooks; database/ models)
-> Core (core/: infrastructure, static classes, no business logic)
-> Config (config/: reads .env via Common.getEnv*, exposes `config`)
-> .env
The core layer never imports application code statically. Each core loads a single
application entry point at runtime (register.*.js) through the hardened register
loader — Inversion of Control keeps the arrow pointing one way.
.
├── config/ # Centralized config (one file per domain) -> @config
├── core/ # Core layer (static classes) -> @core
│ ├── common.core.js + common/ # Shared utils + env readers
│ ├── runtime · logger · error · register
│ ├── database · cron · queue
│ ├── jwt · mailer · hooks · redis
│ ├── express · socket · validator
│ └── bootstrap.core.js # Boot orchestrator
├── app/ # Application layer -> @app
│ ├── http/controllers|middlewares|validators
│ ├── routes/ # web.route, api.route, register.route
│ ├── jobs/register.job.js # (Cron) => {}
│ ├── queue/register.queue.js # (Queue) => {}
│ ├── socket/register.socket.js # (io, Socket) => {}
│ └── hooks/register.hook.js # { before, after, shutdown }
├── database/ # -> @database
│ ├── models/ # Sequelize models
│ ├── migrations/ # up/down migrations (tracked in _migrations)
│ └── seeders/ # data seeders
├── modules/ # Optional feature modules (entry: <name>.module.js)
├── storage/ # Local file storage / uploads -> @storage
├── tests/ # Jest test suite
├── create-rebe/ # The `npm create rebe` scaffolder package
├── docs/ # Per-core API reference
├── scripts/cli.js # Project CLI dispatcher (npm run cli) + scripts/cli/
├── index.js # Entry: dotenv -> module-alias -> runtime -> Bootstrap.run()
└── ecosystem.config.js # PM2 (fork, single instance)
index.js -> dotenv -> module-alias -> runtime.core -> Bootstrap.run()
1. error handlers 2. Hooks.before 3. Redis.connect (if enabled)
4. Database.connect (if enabled) 5. Express.create -> { app, server }
6. Socket.attach 7. Cron + Queue 8. Express.listen 9. Hooks.after
10. SIGINT/SIGTERM -> graceful shutdown
There is no response.core. Every API handler returns a manual envelope:
res.json({ status: true, code: 200, message: 'OK', data: null, meta: null })Validation failures add an errors array (422). Unhandled errors and 404s are
formatted by error.core (JSON or HTML).
- docs/ — per-core API reference (one file per core).
- SECURITY.md — security model, hardening checklist, audit findings.
.env.example— every configuration variable with its default.
npm run dev # nodemon (development)
npm start # node . (production)
npm test # jest
npm run format # prettier --write .
npm run cli -- helpThe project CLI (npm run cli -- <command>) scaffolds code and manages the database.
# Project / keys
npm run cli -- setup [--upgrade] # .env + install + keys (--upgrade runs npm-check-updates)
npm run cli -- key:generate # APP_KEY
npm run cli -- key:jwt [--refresh] # JWT_SECRET / JWT_REFRESH_SECRET
# Scaffolding (every make: supports --module=<name>; see docs/Make.md)
npm run cli -- make:model <Name> # model + matching create-table migration
npm run cli -- make:migration <name> # blank up/down migration
npm run cli -- make:seed <Name> # seeder
npm run cli -- make:controller <Name> [--resource] [--api]
npm run cli -- make:middleware <Name> # handle() middleware class
npm run cli -- make:validator <Name> # zod schemas
npm run cli -- make:route <name> # route group file
npm run cli -- make:job|queue|socket <Name> # background / realtime modules
npm run cli -- make:hook # { before, after, shutdown }
npm run cli -- make:resource <Name> [--api] # controller + model + migration + validator + route
npm run cli -- make:module <name> # full mini-app module (http/, routes, jobs, queue, socket, hooks, data)
# Database
npm run cli -- db:migrate # run pending migrations (alias: migrate)
npm run cli -- db:rollback [--step=N] # roll back the last batch (alias: rollback)
npm run cli -- db:reset [--seed] # drop all tables → migrate (alias: reset)
npm run cli -- db:refresh [--seed] # rollback all via down() → migrate
npm run cli -- db:fresh [--seed] # alias of db:reset
npm run cli -- db:status # applied vs pending migrations
npm run cli -- db:wipe # drop all tables (no migrate)
npm run cli -- db:seed [--all] [--class=Name] # run default/named seeder (alias: seed)
npm run cli -- db:seed-all # run every seeder (alias: seed-all)Migrations are tracked in a _migrations table and ordered globally by their
YYYYMMDDHHmmss_ filename prefix. Once migrations own the schema, keep DB_FORCE /
DB_ALTER off in production. See docs/Migration.md and
docs/Seeder.md.
Group a feature's models, routes, migrations, seeders, jobs, queue, and socket
handlers under modules/<name>/ behind a single entry file
(<name>.module.js). It's additive — the flat layout keeps working, and a project
with no modules/ directory is unaffected. Scaffold one with
npm run cli -- make:module <name>; see docs/Modules.md.
MIT