It's just that - a vanilla web server with some of my modules with no thirdparty modules. Yet. It provides an uniform way of server development for serving files and API-endpoints both.

Usage no npm install needed!

<script type="module">
  import nodeWebServerWithStuff from '';



This is a vanilla JS web server made with the nodeJS buit-in http module. It also includes a couple of modules I wrote to make my life easier (up2require and c4console). I made this module with my personal learning/development process in mind. Got used to use Heroku, so it's ready for the heroku deploy (respects its env.PORT by default). It also by default will run in production mode on it and in dev mode locally.


npm i node-web-server-with-stuff


Most basic setup-and-run would be


In this case it will run with default settings: port 3000 locally and whichever Heroku provides for it up there, dev-mode locally and prod-mode up there, /public/ folder for pages supposed to be present in the project root directory and it's better be having at least an index.html, /api/ folder for various API handlers supposed to be present at the root too, but it's not the end of the world if it isn't there. By default API endpoints are secured by one system-level variable ADMIN_KEY, so you may want to set it in Settings tab on Heroku. If none set the key value defaults to its name "ADMIN_KEY". But custom security access checks are much preferred and by default they would be loaded from /access/ folder.

But imported module also can provide some helper functions and/or handle an options object.

const {server, up2, c} = require('node-web-server-with-stuff')
const options = {/* dev: false, port: 5500 */, public: '/front'}
const {dev} = server
if (dev) require = up2(require)
// ...

Here options object provides a way to configure the server (it can take dev mode and port even though in this instance they are skipped). Here it allows to select another folder for public files. Also there are two functions imported here. up2 is an alias for upgradeToUpdate from my up2require module and c is my shorthand for an advanced console.log variant from my c4console module. In this example I let server decide if it's a dev run or a prod one and use or don't use up2 based on that.

We can also configure the APIs. Here is an elaborate example. It provides additional given things (like the database connection or additional functions) to any custom check function or API-handler that cares to take them.

process.env.ADMIN_KEY = '5UPP3Rpassw0rd' // you would do this in a separate .gitignore-d file
const {server} = require('node-web-server-with-stuff')

const {validateFn, rules, anything} = require('./from/your/modules.js')
const conn = db.connect(/* credentials */) // your database of choice connection here
const options = {/* secure: false, */ accessors: '/checks', api: ['/data', '/secret_api'],
  given: {conn, validateFn, rules, anything} }

And then in the /data (or /secret_api) folder could be for example a notes.js (or notes.cjs) file (those API-handlers can also be deep in the sufolders) and in such file would be

module.exports = function ({request, granted, conn, validateFn, rules, anything}) {
  // and here would be the function body, and it's supposed to simply
  // return what should be sent to the client by this API-endpoint
  // data received from the client is available as a promise in
  // granted - is the data returned by the check function

This function will handle requests with any http methods at URL /data/notes and those would have to have the cookie key=5UPP3Rpassw0rd or they would be rejected before the handler function will be called. Also that admin-cookie would be renewed for half an hour. To use custom checks we will have to add them in the /checks/ folder as .js or .cjs files. For example there can be user.js that provides a function for checking if user is actually logged in.

module.exports = async ({request, response, conn}) => {
  const user = await conn.collection('users').findOne({token: request.cookie.token})
  if (user) return user.login // this returned value will be passed to the
                             // API handler above as granted (or grant)

And if this function will throw or return falsy value the API will gracefully fail to provide the data requested. Otherwise a handler will be called to handle the requested API. The file can also look like this

module.exports = {
  GET: {access: 'guest', handler({conn}) {
    // this one will require no credentials whatsoever
    // get notes via the connection and simply return them
  POST: {access: 'user', handler({req, resp, grant, conn, validateFn, rules}) {
    // this one will use the checks.user(request, response, given) to check
    // if user is recognised and it can for example get, validate and save
    // new notes for him or throw - needs to throw JSON string to send it
    // to the client
  DELETE: {access: 'moderator', handler({conn}) {
    // this one will use the checks.moderator(request, response, given) to
    // check user and it can for example delete some notes

In these examples request (or req) and response (or resp) objects have all the getters, setters and methods provided by the httpity module. For example is a promise giving us the cumulative object from the request body and request URL querystring both parsed if needed. And granted (or grant) may for example contain an id, login or name of the user confirmed (returned) by the used checks.method() or any other internal information corresponding to the successful access check.