npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

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

Readme

Nodwell Framework - Laravel-like Structure for Node.js

Nodwell Node.js License

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 dev

Visit 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-project

or:

npx create-nodwell my-project

The generator will prompt for setup options and scaffold your application.

For more information about the generator, visit: create-nodwell


📚 Documentation

Getting Started

Core Concepts

The Basics

Database & Models

Security & Authentication

Advanced Features

API Development

Testing & Development

Architecture


🏗️ 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:react

This 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:5173

Production Build

# Build React app for production
npm run react:build

# Start Nodwell in production mode
NODE_ENV=production node public/index.js

Creating Components & Pages

# Create a React component
node joker make:react-component Header

# Create a React page
node joker make:react-page Dashboard

API 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 migrate

3. Run Application

node public/index.js

4. 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:status

Migration 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.js

Debug Mode

node debug.js

📖 Best Practices

  1. Keep Controllers Thin

    • Delegate business logic to Services
    • Use controllers only for request/response handling
  2. Use Services for Complex Logic

    • Reusable business logic
    • Easy to test
    • Can be shared across controllers
  3. Follow Naming Conventions

    • Consistent naming makes code predictable
    • Easier for team collaboration
    • Auto-resolution depends on correct naming
  4. Leverage Middleware

    • Authentication/Authorization
    • Request validation
    • CORS handling
    • Rate limiting
  5. 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.