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

yml-mvc-router

v0.1.0

Published

A configurable, Express-compatible routing module that maps routes from YAML to controllers following the MVC pattern

Readme

yml-mvc-router

A configurable, Express-compatible routing module that maps routes from YAML to controllers following the MVC pattern. Make your Express apps declarative, predictable, and easier to maintain.

🚀 Features

  • YAML Route Configuration - Define routes declaratively in routes.yml
  • Automatic Controller Resolution - Smart loading from your controllers directory
  • Smart Response Detection - Controller return values decide JSON vs view rendering
  • Asset Injection - Per-route CSS/JS assets automatically injected into templates
  • Hot Reload - Development mode automatically reloads routes on file changes
  • Route Inspector - Visual debugging tool at /routes
  • Middleware Support - Easy middleware configuration and chaining
  • Route Groups - Organize routes with shared prefixes and middleware
  • EJS Ready - Works out-of-the-box with EJS (extensible for other view engines)

📦 Installation

npm install yml-mvc-router

npm version License: MIT Node.js CI

🏁 Quick Start

const express = require('express');
const ymlRouter = require('yml-mvc-router');

const app = express();

// Basic setup
app.use(ymlRouter({
  routes: './routes/routes.yml',
  controllers: './controllers'
}));

app.listen(3000);

routes/routes.yml

/:
  controller: HomeController.index
  method: GET

/users/:id:
  controller: UserController.show
  method: GET

controllers/HomeController.js

exports.index = async ({ view }) => {
  return view('home', { title: 'Welcome!' });
};

controllers/UserController.js

exports.show = async ({ params }) => {
  return { userId: params.id }; // Returns JSON
};

📋 Configuration Options

app.use(ymlRouter({
  routes: './routes/routes.yml',      // Path to routes file
  controllers: './controllers',       // Controllers directory
  middlewares: './middlewares',       // Middlewares directory  
  views: './views',                   // Views directory
  assets: './public',                 // Static assets directory
  engine: 'ejs',                      // View engine name
  watch: true,                        // Enable hot reload (dev)
  devInspector: true,                 // Enable /routes inspector
  controllerExt: ['.js'],             // Controller file extensions
  resolveController: null,            // Custom controller resolver
  plugins: []                         // Plugin array (future)
}));

🗺️ routes.yml Schema

Basic Routes

# Simple route
/:
  controller: HomeController.index
  method: GET

# With middleware and assets
/users/:id:
  controller: UserController.show
  method: GET
  middlewares:
    - auth
    - rateLimiter
  assets:
    css:
      - css/user.css
    js:
      - js/user.js

# Force response type
/api/data:
  controller: ApiController.getData
  method: GET
  response: json  # or 'view'

Route Groups

/admin:
  prefix: /admin
  middlewares:
    - auth
    - adminOnly
  children:
    /dashboard:
      controller: AdminController.dashboard
      method: GET
    /users:
      controller: AdminController.users
      method: GET

Middleware with Options

/api/posts:
  controller: PostController.create
  method: POST
  middlewares:
    - auth
    - { name: rateLimiter, options: { max: 5, windowMs: 60000 } }

🎮 Controller Contract

Controllers are plain Node.js modules that export functions. Each action receives a context object:

exports.actionName = async (context) => {
  // Context contains:
  const { 
    req, res, next,           // Express objects
    params, query, body,      // Request data
    view,                     // View helper function
    route,                    // Route metadata
    services                  // DI container (future)
  } = context;
  
  // Return options:
  return view('template', data);        // Render view
  return { view: 'template', data };    // Explicit view
  return { someData: 'value' };         // JSON response
  return null;                          // Call next()
  
  // Or manipulate res directly
  res.json({ custom: 'response' });
};

Response Types

View Rendering:

// Using view helper (recommended)
exports.show = async ({ view, params }) => {
  const user = await getUserById(params.id);
  return view('user/profile', { user });
};

// Explicit view object
exports.show = async ({ params }) => {
  const user = await getUserById(params.id);
  return { 
    view: 'user/profile', 
    data: { user } 
  };
};

JSON Response:

exports.apiEndpoint = async ({ body }) => {
  const result = await processData(body);
  return { success: true, result }; // Auto JSON
};

🔧 Middleware

Create middleware files in your middlewares directory:

middlewares/auth.js

module.exports = (options = {}) => {
  return (req, res, next) => {
    // Your auth logic
    if (!req.headers.authorization) {
      return res.status(401).json({ error: 'Unauthorized' });
    }
    req.user = decodeToken(req.headers.authorization);
    next();
  };
};

middlewares/rateLimiter.js

module.exports = ({ max = 10, windowMs = 60000 } = {}) => {
  return (req, res, next) => {
    // Rate limiting logic
    next();
  };
};

🎨 Asset Management

Assets defined in routes are automatically injected into res.locals.assets:

routes.yml

/dashboard:
  controller: DashboardController.index
  assets:
    css:
      - css/dashboard.css
      - https://cdn.example.com/charts.css
    js:
      - js/dashboard.js

Template (EJS)

<head>
  <!-- Route-specific CSS -->
  <% if (assets && assets.css) { %>
    <% assets.css.forEach(css => { %>
      <link rel="stylesheet" href="<%= css %>">
    <% }); %>
  <% } %>
</head>

<body>
  <!-- Your content -->
  
  <!-- Route-specific JS -->
  <% if (assets && assets.js) { %>
    <% assets.js.forEach(js => { %>
      <script src="<%= js %>"></script>
    <% }); %>
  <% } %>
</body>

🔥 Hot Reload & Development

Automatic Reloading

In development mode (NODE_ENV !== 'production' or watch: true), yml-mvc-router automatically watches your routes.yml file and reloads routes when changed.

Route Inspector

Visit /routes in your browser to see:

  • All registered routes
  • Controller mappings
  • Middleware chains
  • Asset configurations
  • Registration status and errors

The inspector auto-refreshes every 5 seconds and is only available in development mode.

🧪 Testing

Run the example application:

git clone <repository>
cd yml-mvc-router
npm install
npm run example

Then visit:

  • http://localhost:3000 - Home page
  • http://localhost:3000/about - About page
  • http://localhost:3000/api/status - JSON API
  • http://localhost:3000/users/1 - User profile with middleware
  • http://localhost:3000/admin/dashboard - Admin area (route groups)
  • http://localhost:3000/routes - Route inspector

Run tests:

npm test
npm run test:watch

📁 Example Project Structure

my-app/
├── app.js
├── routes/
│   └── routes.yml
├── controllers/
│   ├── HomeController.js
│   ├── UserController.js
│   └── ApiController.js
├── middlewares/
│   ├── auth.js
│   └── rateLimiter.js
├── views/
│   ├── layout.ejs
│   ├── home.ejs
│   └── user.ejs
└── public/
    ├── css/
    └── js/

🚨 Error Handling

yml-mvc-router forwards all controller errors to Express error handlers:

// Controller throws error
exports.problematic = async () => {
  throw new Error('Something went wrong');
};

// Express error handler catches it
app.use((err, req, res, next) => {
  console.error('Controller error:', err.message);
  res.status(500).json({ 
    error: 'Internal server error',
    message: err.message 
  });
});

🔒 Security Considerations

  • Controllers and middleware are resolved only from configured directories
  • Route inspector is disabled in production by default
  • No code execution from YAML content
  • Standard Express security best practices apply

🛣️ Roadmap

v0.2 (Next)

  • [ ] Plugin system for extensibility
  • [ ] View adapter for Pug, Handlebars, React SSR
  • [ ] CLI tools (yml-router:list, yml-router:validate)
  • [ ] Advanced middleware configuration

v1.0 (Future)

  • [ ] TypeScript definitions
  • [ ] Asset bundling and optimization
  • [ ] Route caching for production
  • [ ] Performance metrics and monitoring
  • [ ] Advanced debugging tools

🤝 Contributing

Contributions are welcome! Please read our contributing guidelines and submit pull requests for any improvements.

📄 License

MIT License - see LICENSE file for details.

🆘 Support

🤝 Contributing

Contributions, issues and feature requests are welcome! See CONTRIBUTING.md for details.

Development Setup

# Clone the repository
git clone https://github.com/Pinkuagrawal28/yml-mvc-router.git
cd yml-mvc-router

# Install dependencies
npm install

# Run tests
npm test

# Run example app
npm run example

# Visit http://localhost:3000 to see it in action

Built with ❤️ for the Express.js community by Pinku Agrawal