Skip to content

Repository files navigation

Node Framework

A batteries-included MVC framework for Node.js

Build production-ready REST APIs and real-time apps — without reinventing the wheel.

VersionLicenseNode.jsExpressSocket.IO

CITestsPRs WelcomeMaintainednpm create


Quick Start · Features · Documentation · Changelog · Contributing


Why Node Framework?

Most Node.js projects start the same way: wire up Express, configure CORS, add JWT, set up a logger, connect a database, add validation... before writing a single line of business logic.

Node Framework handles all of that — opinionated where it matters, extensible where it counts.

npm create @refkinscallv/node-framework my-app
cd my-app && npm run dev

Your app is running. Routes, auth, database, sockets, logging — already wired.


✨ Features

Core

FeatureDescription
🚀Express 5.xLatest Express with async error propagation
Socket.IO 4.xReal-time events with optional JWT auth per connection
🗄️Sequelize ORMAuto-loads models, associations, migrations, seeds
🔄TransactionsDatabase.transaction() — auto commit/rollback
🔒JWT AuthAccess + refresh tokens with issuer/audience validation
🛡️Auth Middlewareauthenticate, role(), can(), optional — ready to use
🗃️CacheIn-memory TTL cache: remember, pull, increment
🚦Rate LimitingGlobal auto-wired + RateLimit.strict() per route
🩺Health CheckGET /health — uptime, memory, env — auto-registered
Env ValidationFail-fast on missing required env vars at startup

Developer Experience

FeatureDescription
📦BaseControllerhandle() wraps async — zero boilerplate try/catch
🏗️BaseServiceStructured responses: success(), fail(), conflict()
📨MailerEJS templates + raw HTML, SMTP via Nodemailer
📝LoggerWinston — console in dev, rotating files in prod
🔗HooksLifecycle events: before, after, shutdown
🛠️HelpersEnv, Str, Arr, Hash, Url, RateLimit utilities
🔍Zod ValidationSchema-based request validation
🐳DockerMulti-stage Dockerfile + docker-compose with MySQL
🧪205+ TestsJest unit + Supertest integration — coverage enforced
🎨Code QualityESLint + Prettier + Husky pre-commit hooks

🚀 Quick Start

Option 1 — npm create (Recommended)

# npm
npm create @refkinscallv/node-framework my-app
# pnpm
pnpm create @refkinscallv/node-framework my-app
# yarn
yarn create @refkinscallv/node-framework my-app

The CLI scaffolds the project, installs dependencies, and generates .env with secure JWT keys.

Option 2 — Clone

git clone https://github.com/refkinscallv/node-framework.git my-app
cd my-app
npm run setup # copies .env.example → .env + generates JWT secrets
npm run dev

Option 3 — Docker

git clone https://github.com/refkinscallv/node-framework.git my-app
cd my-app && cp .env.example .env
# Edit .env with your settings
docker compose up -d

Available Scripts

npm run dev # Start with nodemon (auto-reload)
npm run dev:debug # Start with Node.js inspector
npm start # Production
npm test# Jest with coverage
npm run lint # ESLint --fix
npm run format # Prettier
npm run db:migrate # Run migrations
npm run db:seed # Run seeders
npm run db:reset # Drop + recreate tables
npm run logs:clear # Clear log files

📁 Project Structure

my-app/
├── app/ # Your application code
│ ├── config.js # Centralized configuration
│ ├── hooks/register.hook.js # Lifecycle hooks (before/after/shutdown)
│ ├── http/
│ │ ├── controllers/
│ │ │ └── base.controller.js # Response helpers + handle()
│ │ ├── middlewares/
│ │ │ ├── auth.middleware.js # JWT auth + role() + can() + optional
│ │ │ └── register.middleware.js
│ │ └── validators/ # Zod schema validators
│ ├── models/ # Sequelize models (*.model.js)
│ ├── routes/
│ │ ├── register.route.js # Imports all route files
│ │ ├── web.route.js
│ │ └── api.route.js
│ ├── services/
│ │ └── base.service.js # Structured response builders
│ └── sockets/register.socket.js # Socket.IO event handlers
│
├── core/ # Framework internals
│ ├── boot.core.js # Boot sequence
│ ├── cache.core.js # In-memory cache
│ ├── database.core.js # Sequelize + transaction()
│ ├── env.validator.js # Startup env validation
│ ├── express.core.js # Express + /health + rate limiter
│ ├── jwt.core.js # JWT sign/verify/refresh
│ ├── logger.core.js # Winston logger
│ ├── mailer.core.js # Nodemailer
│ ├── socket.core.js # Socket.IO + JWT auth
│ └── helpers/
│ ├── env.helper.js # Env var access with type casting
│ ├── arr.helper.js # Array utilities
│ ├── hash.helper.js # bcrypt, sha256, uuid, hmac
│ ├── rateLimit.helper.js # Per-route rate limiter factory
│ ├── str.helper.js # String utilities
│ └── url.helper.js # URL generation
│
├── Dockerfile # Multi-stage (dev + production)
├── docker-compose.yml # App + MySQL
├── .env.example # Environment variable template
└── package.json

📖 Usage Examples

Controllers & Services

// app/services/user.service.jsconstBaseService=require('@app/services/base.service')constDatabase=require('@core/database.core')module.exports=classUserServiceextendsBaseService{staticasyncgetAll(){constUser=Database.getModel('User')constusers=awaitUser.findAll()returnthis.success('Users retrieved',users)}staticasyncstore(body){constUser=Database.getModel('User')constexisting=awaitUser.findOne({where: {email: body.email}})if(existing)returnthis.conflict('Email already registered')constuser=awaitUser.create(body)returnthis.created('User created',user)}}
// app/http/controllers/user.controller.jsconstBaseController=require('@app/http/controllers/base.controller')constUserService=require('@app/services/user.service')module.exports=classUserControllerextendsBaseController{// handle() = zero boilerplate try/catch — errors auto-forwarded to ExpressstaticgetAll=BaseController.handle(async({ req, res })=>{returnBaseController.json(res,awaitUserService.getAll())})staticstore=BaseController.handle(async({ req, res })=>{returnBaseController.json(res,awaitUserService.store(req.body))})}

Routing with Auth & Rate Limiting

// app/routes/api.route.jsconstRoutes=require('@refkinscallv/express-routing')constAuthMiddleware=require('@app/http/middlewares/auth.middleware')constRateLimit=require('@core/helpers/rateLimit.helper')constAuthController=require('@app/http/controllers/auth.controller')constUserController=require('@app/http/controllers/user.controller')Routes.group('api',()=>{// Public — rate-limitedRoutes.post('auth/login',[AuthController,'login'],[RateLimit.strict()])Routes.post('auth/register',[AuthController,'register'],[RateLimit.strict()])// Authenticated — scoped middleware blockRoutes.middleware([AuthMiddleware.authenticate],()=>{Routes.get('profile',[UserController,'profile'])Routes.put('profile',[UserController,'update'])// Admin onlyRoutes.group('admin',()=>{Routes.controller('users',UserController)},[AuthMiddleware.role('admin')])})})

Cache

constCache=require('@core/cache.core')// Cache database results for 5 minutesconstusers=awaitCache.rememberAsync('users:all',300,async()=>{returnawaitUser.findAll()})// One-time token (pull = get + delete)Cache.set('reset:token:abc',userId,900)constid=Cache.pull('reset:token:abc')// Rate counterif(Cache.increment(`login:fails:${ip}`)>=5){returnBaseController.unauthorized(res,'Too many failed attempts')}

Database Transactions

constDatabase=require('@core/database.core')awaitDatabase.transaction(async(t)=>{constuser=awaitUser.create({name: 'Alice',email: 'alice@example.com'},{transaction: t})awaitProfile.create({userId: user.id,bio: '...'},{transaction: t})awaitWallet.create({userId: user.id,balance: 0},{transaction: t})// All created atomically — rolls back if any step fails})

Socket.IO with JWT Auth

// .envSOCKET_AUTH_ENABLED=true// app/sockets/register.socket.jsmodule.exports={register(io){io.on('connection',(socket)=>{// socket.user = decoded JWT payload (when SOCKET_AUTH_ENABLED=true)console.log(`${socket.user.email} connected`)socket.on('message',(data)=>{io.to(socket.user.roomId).emit('message',{from: socket.user.email,
...data})})})}}// Client-sideconstsocket=io('http://localhost:3030',{auth: {token: 'your-jwt-token'}})

Environment Validation

// .envREQUIRED_ENV=JWT_SECRET,DB_HOST,MAIL_USER// The app throws a clear error on startup if any are missing:// Error: Missing required environment variables: JWT_SECRET, DB_HOST

Health Check (automatic)

GET /health
{
"status": true,
"code": 200,
"message": "OK",
"data": {
"app": "My App",
"env": "production",
"uptime": 3600,
"timestamp": "2026-05-25T10:00:00.000Z",
"memory": { "rss": "85 MB", "heapUsed": "42 MB", "heapTotal": "56 MB" }
}
}

⚙️ Environment Variables

Copy .env.example to .env and configure:

# AppAPP_NAME=My AppAPP_PORT=3030APP_URL=http://localhost:3030APP_TIMEZONE=Asia/JakartaNODE_ENV=development# Required env validation (comma-separated)REQUIRED_ENV=JWT_SECRET,DB_HOST# JWT (auto-generated by npm run setup)JWT_SECRET=JWT_REFRESH_SECRET=JWT_EXPIRES_IN=1hJWT_REFRESH_EXPIRES_IN=7d# DatabaseDB_ENABLED=falseDB_DIALECT=mysqlDB_HOST=localhostDB_PORT=3306DB_NAME=databaseDB_USERNAME=rootDB_PASSWORD=# SocketSOCKET_AUTH_ENABLED=false# Rate LimitingRATE_LIMIT_ENABLED=trueRATE_LIMIT_MAX=200RATE_LIMIT_WINDOW_MS=900000# MailMAIL_HOST=smtp.gmail.comMAIL_PORT=587MAIL_USER=MAIL_PASSWORD=# ServerSERVER_HTTPS=false

🧪 Testing

npm test# All tests with coverage
npm run test:unit # Unit tests only
npm run test:watch # Watch mode

Coverage thresholds (enforced): branches 52% · functions 65% · lines/statements 55%

Tests are located in tests/unit/ and tests/integration/.


🐳 Docker

Development:

docker compose up

Production build:

docker build --target production -t my-app .
docker run -p 3030:3030 --env-file .env my-app

🔐 Security Checklist

  • Change JWT_SECRET and JWT_REFRESH_SECRET (use npm run setup)
  • Set NODE_ENV=production in production
  • Enable HTTPS (SERVER_HTTPS=true) with valid SSL certificates
  • Configure CORS origin in app/config.js (not *)
  • Set RATE_LIMIT_ENABLED=true and tune limits
  • Use strong database passwords
  • Never commit .env to version control

📦 Tech Stack

LayerTechnology
WebExpress.js 5.x
Real-timeSocket.IO 4.x
DatabaseMySQL + Sequelize 6.x
AuthJSON Web Tokens (jsonwebtoken)
ValidationZod 4.x
Hashingbcrypt + Node.js crypto
EmailNodemailer
LoggingWinston + daily-rotate-file
SecurityHelmet + CORS + express-rate-limit
TemplatingEJS
TestingJest 30 + Supertest
QualityESLint 10 + Prettier + Husky

🗺️ Roadmap

  • Redis cache adapter
  • Queue / background jobs (BullMQ)
  • PostgreSQL + SQLite dialect examples
  • OpenAPI / Swagger auto-generation
  • CLI scaffold for controllers, services, models

Have an idea? Open a feature request


🤝 Contributing

Contributions are welcome! Please read CONTRIBUTING.md first.

git clone https://github.com/refkinscallv/node-framework.git
cd node-framework && npm run setup
npm run dev
  1. Fork → branch (feat/my-feature) → commit → PR
  2. All PRs require passing tests: npm test
  3. Follow the existing code style (ESLint + Prettier)

📄 License

MIT © Refkinscallv


📬 Author

Refkinscallv


📋 Changelog

See CHANGELOG.md for full version history.

VersionDateHighlights
3.0.22026-05-25Auth Middleware, Cache, Rate Limiting, Health Check, Socket JWT Auth, DB Transactions, Env Validation, Docker, create-cli v3
2.1.02026-04-25JWT refresh tokens, Setup script, Logger optimizations
2.0.02026-03-11BaseController.handle(), BaseService shortcuts, major bug fixes
1.0.02026-01-04Initial release

If this project helps you, please consider giving it a ⭐ on GitHub — it helps others discover it!

Star on GitHub

About

A modern and comprehensive Node.js MVC framework with Express, Socket.IO, Sequelize ORM, and real-time capabilities for building scalable web applications

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages