nodwell
v1.3.2
Published
Modern Full-Stack JavaScript Framework - Laravel-inspired Node.js framework with enhanced Leaf templating, improved validation, and better developer experience
Maintainers
Readme
Nodwell Framework - Laravel-like Structure for Node.js
Nodwell is a Laravel-inspired framework for Node.js that brings Laravel's elegant architecture, naming conventions, and developer experience to the Node.js ecosystem.
🚀 Quick Start
# Install dependencies
npm install
# Set up your environment
cp .env.example .env
# Run migrations
node joker migrate
# Start development server
npm run devVisit http://localhost:3000 and you're ready to build!
🛠️ Create a New Project
To create a new Nodwell project, use the standalone generator package:
npm create nodwell@latest my-projector:
npx create-nodwell my-projectThe generator will prompt for setup options and scaffold your application.
For more information about the generator, visit: create-nodwell
📚 Documentation
Getting Started
- Installation Guide - Complete setup instructions
- Quick Start Tutorial - Build your first blog application
- Configuration - Configure your application
- Directory Structure - Understand the Laravel-style organization
Core Concepts
- API Reference - Complete API documentation
- Architecture Overview - Framework architecture
- Zero-Import Development - Global facades and helpers
- Service Container - Dependency injection
The Basics
- Routing - Define application routes
- Controllers - Handle HTTP requests
- Middleware - Filter HTTP requests
- Views - Render templates with Leaf Engine
- Validation - Validate incoming data
- Error Handling - Handle errors gracefully
Database & Models
- Database - Database connections & configuration
- Migrations - Database schema management
- Jumper ORM - Eloquent-style ORM for Node.js
- Eloquent Guide - Model relationships & queries
- Seeders - Populate database with test data
Security & Authentication
- Authentication - User authentication system
- Authorization - Access control & policies
- Sessions - Session management
- Social Auth - OAuth integration
Advanced Features
- Caching - Performance optimization
- Queues - Background job processing
- Events - Event-driven architecture
- Mail - Email sending
- Notifications - User notifications
- File Storage - File uploads & management
- WebSockets - Real-time communication
- Task Scheduling - Automated tasks
- Rate Limiting - API rate limiting
- Localization - Multi-language support
- Search - Full-text search capabilities
API Development
- API Resources - Transform API responses
- API Versioning - Version your APIs
- CORS - Cross-origin resource sharing
Testing & Development
- Testing - Write and run tests
- CLI (Joker) - Command-line interface
- Health Checks - Monitor application health
- Debugging - Debug your application
- Performance - Performance monitoring
Architecture
- AutoLoader - Zero-import development
- Service Container - Dependency injection
- Facades - Static interfaces
- Enums - Type-safe enumerations
- Traits - Code reusability
🏗️ Architecture Overview
Nodwell brings Laravel's architecture to Node.js:
🎯 Zero-Import Development
// No imports needed - everything is global
Route.get('/', 'HomeController@index');
Auth.check();
Cache.remember('key', 3600, () => expensiveOperation());🏭 Service Container
// Dependency injection with automatic resolution
const userService = container.make('UserService');🎭 Facade Pattern
// Static interfaces to underlying services
DB.table('users').where('id', 1).first();
Mail.to(user.email).send(new WelcomeEmail());📊 Jumper ORM (Eloquent-style)
class User extends Model {
// Relationships
posts() {
return this.hasMany(Post);
}
}
// Query builder
const users = await User.where('active', true).with('posts').get();🎨 Leaf Template Engine
<!-- resources/views/welcome.leaf -->
<h1>Hello {{ $name }}!</h1>
@if($user)
<p>Welcome back, {{ $user.name }}!</p>
@endif📦 Core Features
- ✅ Laravel-style Routing - RESTful routes with middleware
- ✅ Eloquent ORM - ActiveRecord pattern for database operations
- ✅ Authentication & Authorization - Complete user management
- ✅ Session Management - Cookie-based sessions
- ✅ Caching System - Multiple cache drivers (Redis, Memory, File)
- ✅ Queue System - Background job processing
- ✅ Event System - Observer pattern implementation
- ✅ Mail System - Email sending with templates
- ✅ File Storage - Local and cloud storage
- ✅ WebSockets - Real-time communication
- ✅ Task Scheduling - Cron-like job scheduling
- ✅ Rate Limiting - API throttling
- ✅ Localization - Multi-language support
- ✅ Validation - Request validation with custom rules
- ✅ Testing Framework - Unit and integration tests
- ✅ CLI Tool (Joker) - Artisan-like command interface
- ✅ Health Checks - Application monitoring
- ✅ API Versioning - Versioned API endpoints
- ✅ Middleware Pipeline - Request/response filtering
- ✅ Database Migrations - Schema versioning
- ✅ Seeders - Database population
- ✅ Social Authentication - OAuth integration
- ✅ Performance Monitoring - Built-in profiling
- ✅ React Support (Optional) - Modern frontend with Vite build tool
Optional React Integration
Nodwell provides optional React support for building modern SPAs. React is not included by default to keep the framework lightweight. Install it when you need a JavaScript frontend:
Installation
# Install React support with one command
node joker install:reactThis command automatically:
- Adds React dependencies (react, react-dom)
- Configures Vite build tool
- Sets up project structure in
resources/react/ - Creates development and build scripts
- Installs all required packages
Development Workflow
# Terminal 1: Start Nodwell backend
node joker serve
# Terminal 2: Start React dev server
npm run react:dev
# Visit http://localhost:5173Production Build
# Build React app for production
npm run react:build
# Start Nodwell in production mode
NODE_ENV=production node public/index.jsCreating Components & Pages
# Create a React component
node joker make:react-component Header
# Create a React page
node joker make:react-page DashboardAPI Integration
React can seamlessly access your Nodwell API:
// In your React components
fetch('/api/users')
.then(res => res.json())
.then(data => console.log(data));Full Documentation: core/Helpers/REACT_INTEGRATION.md
🔧 Requirements
- Node.js >= 18.0.0
- npm >= 8.0.0
- Database (MySQL, PostgreSQL, SQLite, MongoDB)
📖 Examples
Basic Route
// routes/web.js
const Route = require('../core/Facades/Route');
Route.get('/', function(request, response) {
return response.json({ message: 'Hello Nodwell!' });
});
Route.get('/users', 'UserController@index');Controller
// app/Http/Controllers/UserController.js
class UserController {
async index(request, response) {
const users = await User.all();
return response.json(users);
}
async show(request, response) {
const user = await User.find(request.params.id);
return response.json(user);
}
}
module.exports = UserController;Model
// app/Models/User.js
const Model = require('../../core/ORM/Model');
class User extends Model {
// Table name (optional, defaults to 'users')
static get table() {
return 'users';
}
// Relationships
posts() {
return this.hasMany('Post');
}
// Accessors
getFullName() {
return `${this.first_name} ${this.last_name}`;
}
}
module.exports = User;Middleware
// app/Http/Middleware/Auth.js
class Auth {
handle(request, response, next) {
if (!Auth.check()) {
return response.redirect('/login');
}
next();
}
}
module.exports = Auth;🤝 Contributing
We welcome contributions! Please see our Contributing Guide for details.
📄 License
Nodwell is open-sourced software licensed under the MIT license.
🙏 Acknowledgments
Nodwell is inspired by the Laravel framework and brings its philosophy to the Node.js ecosystem. Special thanks to the Laravel community for the inspiration and the Node.js community for the amazing ecosystem.
Config Files
- Location:
config/ - Naming: lowercase
- Example:
app.js,database.js,auth.js
🚀 Quick Start
1. Environment Setup
Create .env file in root:
``env
APP_NAME=Nodwell
APP_ENV=development
APP_URL=http://localhost:3000
DB_HOST=localhost
DB_PORT=3306
DB_NAME=nodwell
DB_USER=root
DB_PASS=
### 2. Database Setup
```bash
# Create database
mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS nodwell;"
# Run migrations
node joker migrate3. Run Application
node public/index.js4. Access Application
http://localhost:3000/users🎯 Creating Components
Create a Controller
// app/Http/Controllers/PostController.js
class PostController {
constructor(PostService) {
this.postService = PostService;
}
async index(req, res) {
const posts = await this.postService.getAll();
return res.json({ posts });
}
async show(req, res) {
const post = await this.postService.getById(req.params.id);
return res.json({ post });
}
}
module.exports = PostController;Create a Model
// app/Models/Post.js
const Model = require('../../core/ORM/Model');
class Post extends Model {
static table = 'posts';
// Custom methods
async comments() {
return Comment.where('post_id', this.attributes.id).get();
}
}
module.exports = Post;Create Middleware
// app/Http/Middleware/CheckRole.js
module.exports = (req, res, next) => {
const requiredRole = req.route.options?.role;
if (!req.user) {
return res.status(401).json({ error: 'Unauthorized' });
}
if (requiredRole && req.user.role !== requiredRole) {
return res.status(403).json({ error: 'Forbidden' });
}
next();
};Define Routes
// routes/web.js
const router = require('../core/Routing/Router');
// Basic GET route
router.get('/users', 'UserController@index');
// POST route
router.post('/users', 'UserController@store');
// Route with middleware
router.get('/admin', 'AdminController@dashboard', ['Auth']);
// Route with options
router.get('/posts/:id', 'PostController@show', [], {
name: 'posts.show'
});💡 Dependency Injection
The framework automatically resolves dependencies using constructor injection:
class UserController {
constructor(UserService, EmailService) {
this.userService = UserService;
this.emailService = EmailService;
}
store(req, res) {
// Services are auto-injected
}
}🔧 Configuration
Access config values anywhere using the config() helper:
const appName = config('app.name');
const dbHost = config('database.host');
const customValue = config('custom.key', 'default');📚 Key Features
Joker CLI Commands
Powerful code generation with the Joker CLI:
# Controllers, Models, Services
node joker make:controller UserController
node joker make:model User
node joker make:service UserService
node joker make:middleware Auth
# Enums (Type-safe constants)
node joker make:enum UserStatus
# Mails (Pigeon mailers)
node joker make:mail WelcomeEmail
# Jobs (Queue workers)
node joker make:job ProcessImage
node joker queue:work
# Date/Time (Clok)
const { clok } = require('./core/helpers');
clok().format('Y-m-d H:i:s')
# File Handling (Shelf)
const { shelf } = require('./core/helpers');
shelf.put('file.txt', 'content')
# Logging (Insight)
const { insight } = require('./core/helpers');
insight.info('Application started')
# Caching (Cache)
const { cache } = require('./core/helpers');
cache.put('key', 'value', 60)
# Events (Events)
const { event } = require('./core/helpers');
event.dispatch('UserRegistered', { user })
# Task Scheduling (Scheduler)
const { schedule } = require('./core/helpers');
schedule().schedule('task').daily()
# Authentication (Auth)
const { auth } = require('./core/helpers');
auth.attempt({ email, password })
# Authorization (Gate)
const { gate } = require('./core/helpers');
gate.allows('update-post', user, post)
# Notifications (Notify)
const { notify } = require('./core/helpers');
user.notify(new WelcomeNotification())
# Testing Framework
node joker test
node joker test:feature
# API Resources
const { resource } = require('./core/helpers');
resource(UserResource, user)
# Localization (i18n)
const { trans } = require('./core/helpers');
trans('messages.welcome')
# Social Authentication
const { socialite } = require('./core/helpers');
socialite().redirect('google')
# WebSockets (Real-time)
const { broadcast } = require('./core/helpers');
broadcast().toUser(userId, 'event', data)
# Rate Limiting
const Throttle = require('./app/Http/Middleware/Throttle');
router.post('/login', [Throttle.middleware('auth')], Controller@login)
# Search & Filtering
Model.search('term').filter('status', 'active').sortBy('created_at').paginate(15, 1)
# API Versioning
const { apiVersion } = require('./core/helpers');
apiVersion().setCurrentVersion('v2')
# Health Checks
router.get('/health', 'HealthCheckController@index')
# Warden (API Tokens)
const { warden } = require('./core/helpers');
user.createToken('mobile-app', ['read', 'write'])
# Singer (Tinker REPL)
node joker singer
await User.all()
# Traits (Reusable mixins)
node joker make:trait Timestamps
# Views (Leaf Engine templates)
node joker make:view home
# React Support (Optional - Install first)
node joker install:react # Install React with Vite
node joker make:react-component Header # Create React component
node joker make:react-page Dashboard # Create React page
npm run react:dev # Start React dev server
npm run react:build # Build for production
# Migrations
node joker make:migration create_posts_table
node joker migrate
# CORS & Optimization
node joker optimize # Cache routes and config
node joker optimize:clear # Clear all caches
node joker route:list # List all routes
node joker cache:clear # Clear application cache
📖 Full Documentation: JOKER_CLI.md | ENUMS_MAILS_TRAITS_GUIDE.md
✅ Laravel-like Migrations
Version control your database schema with exact Laravel syntax:
# Create migration
node joker make:migration create_users_table
# Run migrations
node joker migrate
# Rollback
node joker migrate:rollback
# Check status
node joker migrate:statusMigration example:
module.exports = {
up: async (schema) => {
await schema.create('users', (table) => {
table.increments('id');
table.string('name');
table.string('email').unique();
table.timestamps();
});
},
down: async (schema) => {
await schema.drop('users');
}
};📖 Full Documentation: MIGRATION_QUICK_START.md | MIGRATIONS_GUIDE.md
✅ Laravel-like Architecture
- MVC pattern
- Service layer
- Middleware pipeline
- Dependency injection container
✅ JUMPER ORM (Eloquent-style)
Powerful ORM with N+1 query prevention and multi-database support:
const Jumper = require('../../core/ORM/Model');
class User extends Jumper {
static table = 'users';
posts() {
return this.hasMany(Post);
}
}
// Find by ID
const user = await User.find(1);
// Query builder
const users = await User.where('active', true).get();
// Eager loading (prevents N+1 queries!)
const posts = await Post.with('user', 'comments').get();
// First result
const admin = await User.where('role', 'admin').first();
// Save model
await user.update({ name: 'New Name' });📖 Full Documentation: JUMPER_INTRO.md | ELOQUENT_ORM_GUIDE.md
✅ Route Helpers
// Generate URL for named route
const url = router.urlFor('posts.show', { id: 1 });
// With query parameters
const fullUrl = router.urlFor('posts.show',
{ id: 1 },
{ page: 2, sort: 'date' }
);⚡ Auto-Loader (No Imports Needed!)
Nodwell features a powerful auto-loader that makes core classes and helpers available globally, eliminating the need for repetitive require statements in your controllers, services, and routes.
// No imports needed! User, Route, Auth, Cache are all global
const user = await User.find(1);
Cache.put('key', 'value');
Event.dispatch('event.name');
Route.get('/home', 'HomeController@index');🛠️ Framework Commands
Check Circular Dependencies
node check-circular.jsDebug Mode
node debug.js📖 Best Practices
Keep Controllers Thin
- Delegate business logic to Services
- Use controllers only for request/response handling
Use Services for Complex Logic
- Reusable business logic
- Easy to test
- Can be shared across controllers
Follow Naming Conventions
- Consistent naming makes code predictable
- Easier for team collaboration
- Auto-resolution depends on correct naming
Leverage Middleware
- Authentication/Authorization
- Request validation
- CORS handling
- Rate limiting
Use Dependency Injection
- Don't manually instantiate services
- Let the container resolve dependencies
- Makes testing easier
🔄 Migration from Traditional Node.js
If migrating from a traditional Node.js structure:
Old Structure → New Structure
controllers/ → app/Http/Controllers/
middleware/ → app/Http/Middleware/
models/ → app/Models/
services/ → app/Services/
routes/web.js → routes/web.js (no change)
config/ → config/ (no change)🐛 Troubleshooting
Controller Not Found
- Ensure file is in
app/Http/Controllers/ - Check filename matches class name
- Verify route uses correct syntax:
'ControllerName@method'
Middleware Not Executing
- Ensure file is in
app/Http/Middleware/ - Middleware must call
next()to continue - Check middleware name in route array
Dependency Injection Fails
- Constructor parameter names must match service names
- Services must be in
app/Services/ - Avoid circular dependencies
📄 License
MIT License - Feel free to use in your projects!
🤝 Contributing
Contributions welcome! Please follow Laravel-like conventions for consistency.
