Automated Server for the Web.


Hi, I am Aden. I give you a CLI to handle a web application or service. I can help you develop and deploy static and dynamic sites or a full featured web application.


You can check what my CLI can do for you at any time with aden -h.

Note: Help us get out of alpha stage, by providing feedback. If you want to get the newest development version, clone my repository and do npm i -g from there.

If I bug you with an error at any point, or you have an idea how I may help you better, feel free to open an issue.

Back to the top.


Standing on the shoulders of giants, I leverage a set of modern open source technologies like Webpack, Babel and Express to deliver on my promises. Although you do not need to know about any of these in detail to get started, I strongly encourage you to read up on the technologies involved.

ECMAScript 6
I am pre-configured to support ECMAScript 6. No need to set up transpilers.
I am built on Nodejs and automate routing setup with Express.
I come with pre-configured babel transpilers and polyfills. You retain full control though.
ECMAScript 6
I aim to distill webpacks wall of configuration into an intuitive automated system.
Back to the top.

Getting Started

Remember, back in the 90s when my big brother was serving the web? Those were amazing times. Lets start with what he could do. But dynamic by nature.

Open a Terminal. Create a project root folder mkdir woa and navigate to it cd woa. There, touch .server. Now I can help you out developing with aden dev.

As you might have noticed, I am now running on port 5000, with ./woa as your root folder. Just open your browser and navigate to http://localhost:5000.

You should get a 404 page, because there's nothing to show yet. Let's create our first content and see what happens.

echo "<h1>Hello Web</h1>" > index.html

Your Browser should greet you with Hello Web.

Back to the top.


Now, that can be done with any static file server. Let's see if you like this:

echo "alert('woa')" > index.js

Check your browser. I just injected the script into your html. You can wrap your html in a layout by using a template engine like handlebars or the default layout attitude.

Back to the top.


As you might have guessed by now, I can also inject stylesheets for you. Try it like this.

echo "h1 { color: #15425F; }" > index.css

Your browser should have updated to our stylesheet by now. But we are still getting that alert, so lets remove that again rm index.js.

Better. We just created a page, that could be deployed as is. I will take care of optimizing your bundles and entry points for fast delivery.

Back to the top.


That one page would be pretty lonely though. Lets get started with our first app.

I like quotes. Let's build a random quote machine!

First, we need a script that gives us a random quote. Create a new folder mkdir quotemachine, navigate to it cd quotemachine and setup an html entry point with

echo "<h1>QuoteMachine</h1>" > index.html`

Now add back javascript with touch quote.js. Open your favorite editor and fill it with:

const quotes = [

module.exports = function getRandomQuote() {
  const index = Math.floor(Math.random() * ((quotes.length - 1) + 1));
  return quotes[index];

I just setup the /quotemachine route for you. Navigate your browser to http://localhost:5000/quotemachine. Nothing happens yet. To add this module to our application, we need to require it from our entry point. touch index.js, open it in your editor and type:

const quote = require('./quote');

Ok, that works. Lets render our quote to the page now, instead of alerting the user. Add a <blockquote id="quote"></blockquote> to our index.html and adjust our entry point script like so:

const quote = require('./quote');
const quoteElement = document.querySelector('#quote');
quoteElement.innerText = quote();

Lets add a button to refresh the quote. After our blockquote, add <button id="quoteButton">Get another quote</button>. From our entry point script we can now do:

const quote = require('./quote');
const quoteElement = document.querySelector('#quote');
const quoteButton = document.querySelector('#quoteButton');
quoteButton.addEventListener('click', () => (quoteElement.innerText = quote()));

Clicking the newly added button on the page should result in the next random quote shown on the page.

Back to the top.


Looks a bit 90s though, lets add some styling. I heard bootstrap gives you a good head-start and is widely used. To be able to add modules to our project we need to initialize npm with npm init --yes, then we can add bootstrap via npm i bootstrap. Create an entry style touch index.css and just put @import "~bootstrap/dist/css/bootstrap.min.css"; at the very top.

Add class="btn btn-primary" to our button element.

Check our app. Looks better. Should do for now.

Back to the top.


If you want to get your quotes from an API, rather than delivering thousands of them with every request, I can help you out as well.

Lets move our getRandomQuote method to the server, by creating a route for our API with mkdir -p api/quote. Move our quote.js there mv quote.js api/quote/quote.js.

In that route we touch api/quote/.get.js. If you give me a wrapped method from that file, I will setup a get controller for you. Open .get.js and add:

const quote = require('./quote');
module.exports = () => (req, res) => res.send(quote());

Lets check if our new endpoint works as expected by navigating to http://localhost:5000/quotemachine/api/quote.

So we can request our quote from the server now, rather than delivering all quotes with our frontend application bundle.

Change our quotemachine/index.js to the following:

const quoteElement = document.querySelector('#quote');
const quoteButton = document.querySelector('#quoteButton');
quoteButton.addEventListener('click', () =>
    .then((res) => res.text())
    .then((text) => (
      quoteElement.innerText = text

All quotes are now produced by our first API endpoint.

We can now link our QuoteMachine as a project from our root, just add <a href="/quotemachine">QuoteMachine</a> to our root index.html.

By the way, you might have noticed, we are using ES6 syntax, like arrow functions. This works out of the box, as I have Babel with an es2015 and env preset on-board. You can adjust Babel by creating a .babelrc file in your root folder.

Back to the top.


If you want to take our application to production, we need a production build. I can do that for you, after you stop the development server, with aden build. The resulting development build in .dist can be moved to a production environment. It contains all dynamic templates. Static output can be found in .dist/public.

Additionally to the dynamic templates and static content, I also generate a pages.json where all the routing and configuration information (Page Graph) is stored, so I can run the application without having to parse the file tree again, for super fast startup in production.

You can start the production build by executing aden start in the root of your application or by pointing aden to it from anywhere with aden start /path/to/myapp.

Back to the top.


If you only built static assets, you can use the output in the .dist/public folder and serve via your CDN or a static application hosting service like or Github Pages.

Your dynamic entry points I can run as a standalone server and serve your app when asked to, as you have seen with a global install npm i -g aden. I can also serve as a package dependency in your project, from where you can leverage my full CLI via npm scripts. Or use me as a library to extend an existing express application.

So I am able to comply with a variety of Node.js hosting services, like Heroku. Check out my repository, where this documentation is ran from.

Back to the top.


I can become overloaded with dynamic entry and API endpoints, that might need additional server resources.

Lets scale our QuoteMachine to four workers with aden start -w 4. I should be running with four worker processes now.

If you want to have another instance with four workers, focusing on the API endpoint, I can do that for you with

aden start -w 4 --focus quotemachine/api/quote -p 5001

I now serve the quote endpoint only, at http://localhost:5001/quotemachine/api/quote. Other entry points like http://localhost:5001/ will not be mounted on this instance.

I hope this helps your operations. That's all for now. If you want to know more, check out my source, I'll be glad to follow up on your issues and feel free to create a PR.

Back to the top.


I come with attitudes to build and serve your application, based on some default Webpack plugins and loaders. You can adjust and/or extend the generated Webpack configuration at any time, via the .server file. Whenever you need an additional loader, you can add it like:

// .server.js
module.exports = {
  webpack: {
    rules: [
      { test: /\.ext?$/, loader: 'another-loader' },

I will add the correct include paths to your loader. I suggest you rather give me a new attitude to handle a file type. Have a look at my default attitudes on how to do that.

I am not a hammer, I am a Nailgun. I shoot whatever I am loaded with. Be careful, my attitudes might hit your foot.

Back to the top.


npm i aden -g => touch .server => aden dev => use filesystem like a webserver of the days of olde (with all modern web-dev goodies).

Back to the top.


You can find the example QuoteMachine code in my repo, where these docs are located. My maintainers are also working on a more advanced documentation (work in progress).

Back to the top.