hbh-der
Dynamic, zero-config Express routing and middleware loader with hot-reload and subdomain support.
Dynamic Express Routes (hbh-der)
๐ A zero-config, filesystem-based Express routing and middleware loader with optional hot reloading and hybrid rendering support.
๐ Features
- โ Zero Manual Routing โ Auto-loads routes based on file structure
- โ Middleware Auto-loader โ Plug in middleware files instantly
- ๐ Hot Reloading โ Watch mode using
chokidar(optional) ๐ฅ - ๐ Hybrid Routes โ Serve API responses or HTML views from the same route
- โก Subdomain Routes โ Handle Subdomains Efficiently
- โ๏ธ Pluggable Config โ Easily override defaults with your own config
- ๐ Nested Routing โ Supports deeply nested directories
- ๐ฆ Smart Middleware Sorting โ CORS and essentials come first
- ๐งช Test Mode โ Load routes/middleware without executing them
- ๐ Categorized Logging โ Structured logs for routes, warnings, errors
- ๐ Extensive Built-in Middlewares โ Robust, ready-to-use middleware collection included out-of-the-box under
Middlewares
๐ฆ Installation
1npm install hbh-der
Or with yarn:
1yarn add hbh-der
๐งฉ Project Structure
Example directory layout:
my-app/
โโโ app/
โ โโโ routes/
โ โ โโโ about.js โ GET /about
โ โ โโโ users/[id].js โ GET /users/:id
โ โโโ middlewares/
โ โ โโโ cors.js โ Applies globally
โ โโโโโโโ logger.js
โโโ hbh-der.config.js โ Optional
โโโ index.js
๐ Quick Start
Create a demo.js:
1import { server } from "hbh-der";3server.start({4 port: 3000,5});
Run it:
1node demo.js
๐ ๏ธ Configuration
Create hbh-der.config.js in your project root:
1import path from "path";3const __dirname = path.join(process.cwd(), "app");5export const directories = {6 __dirname,7 routes: "routes",8 middleware: "middlewares",9};
This is automatically loaded via hbh-ccl. You can optionally pass your own config when starting the server.
๐ Routes
Each file in routes/ becomes an Express route.
๐ File โ Route Mapping
| File Path | Route |
|---|---|
routes/index.js |
/ |
routes/about.js |
/about |
routes/users/[id].js |
/users/:id |
routes/blog/index.js |
/blog |
routes/blog/[slug].js |
/blog/:slug |
๐ Route Exports
Each route should default-export:
- A handler function
- OR an array of route tuples:
1export default [2 ["/hello", (req, res) => res.send("Hi!")],3 ["/goodbye", (req, res) => res.send("Bye!"), { method: "post" }],4];
You can also use query-based routing:
1export default [["/details?mode=edit", handlerFn]];
๐งฑ Middleware
Files in middlewares/ are auto-loaded.
โจ Supported Patterns
1// default export2export default function(req, res, next) { ... }4// factory middleware5export default () => (req, res, next) => { ... }7// named export8export function myLogger(req, res, next) { ... }
Override or disable via config:
1server.start({2 middlewareConfig: {3 "logger.js": { export: "myLogger" }, // use named export4 "auth.js": false, // disable this middleware5 }6});
๐ HybridRoute Support
Routes.HybridRoute returns an Express-compatible middleware function that decides, based on headers or query params, whether to serve the front-end HTML or backend JSON.
1import { Routes } from "hbh-der";3app.get( "/hello", Routes.HybridRoute({4 frontEndHandler: (req, res) => res.send(`<h1>Hello ${req.query.name || "Guest"}</h1>`),5 backEndHandler: (req, res) => res.json({ hello: req.query.name || "Guest" }),6 })7);
๐ SubdomainRouting Support
Use SubdomainRouting to manage subdomains: And ensure the middleware is applied:
1import { Routes, Middlewares } from "hbh-der";2app.use(3 Middlewares.subdomainParser({4 baseDomainLevels: 1 /* based on '.' */,5 reverse: false,6 })7);8app.get(9 "/",10 Routes.SubdomainRouting({11 api: (req, res) => res.send("API subdomain"),12 admin: (req, res) => res.send("Admin subdomain"),13 "blog.api": (req, res) => res.send("Blog under API subdomain"),14 "*": (req, res) =>15 res.send(`Wildcard handler: ${req._subdomains.join(".")}`),16 "/": (req, res) => res.send("Main domain (no subdomain)"),17 })18);
๐ Hot Reloading (watch)
Enable automatic hot-reloading of routes and middleware using chokidar.
โ ๏ธ Hot reloading is intended for development use only. Avoid enabling watch in production environments for stability and performance reasons.
โ Usage
Pass watch: true to server.start():
1import { server } from "hbh-der";3server.start({4 port: 3000,5 watch: true, // enables hot reload6});
This will automatically watch for changes in:
routes/directorymiddlewares/directory
When a file is added, modified, or deleted, the server will reload only the affected route or middleware โ without restarting the entire process.
๐ Logs
Structured logging is available:
1import { logs, detailedLogs, allRoutes } from "hbh-der/utils/Logs.js";3console.log(logs); // raw log array4console.log(detailedLogs.success); // success logs5console.log(allRoutes); // all active routes
๐ง API Reference
server.start(config?)
| Option | Description | Default |
|---|---|---|
port |
Port to run the server | 4000 |
directories |
Override directory config | Auto-detected |
middlewareConfig |
Per-file middleware overrides | {} |
routesConfig |
useType, global middlewares for all routes |
{} |
HybridRoute(app, path, handler, viewName)
Serve both API and view response based on headers or ?api=true.
๐ฌ Test Mode
Use testMode: true to load but not execute middlewares (for testing).
1await loadMiddlewares(app, "middlewares", { testMode: true });
๐งฉ Advanced Usage
Global Middleware Sort
Customize load order:
1middlewareConfig: {2 sort: (a, b) => {3 if (a === "cors.js") return -1;4 return a.localeCompare(b);5 };6}
๐ฆ Built-in Middlewares
hbh-der comes with a robust collection of 40+ pre-made middlewares available under the Middlewares export.
Example usage:
1import { server, Middlewares } from "hbh-der";3app.use(Middlewares.subdomainParser({ baseDomainLevels: 1, reverse: false }));4app.use(Middlewares.logRequest);
๐งช Example Middleware (factory)
1// middlewares/auth.js2export default () => (req, res, next) => {3 if (!req.headers.authorization) {4 return res.status(401).send("Unauthorized");5 }6 next();7};
๐ฃ Credits
Created by HBH Inspired by zero-config routing patterns and filesystem-first architectures.