Nowadays, we usually work with frameworks when we want to set up a frontend application. We enter the terminal and enter something like ng new my-app or npx create-react-app my-app. The cli works it’s magic and sets up an entire application with a whole lot of stuff included. We’re good to go. But what if you just want to build something simple? What if you want to build an app that simply doesn’t have a lot of logic, and doesn’t need a complete framework, like a portfolio website. Or, what if you want to challenge yourself and see if you can build something worthwhile without a framework?


Here you can find the github repository with the project set-up. Feel free to fork it.

Ok, so what exactly do we want?

Let’s say we want to build something non-trivial. We want our app to have the potential to grow, we want to feel secure building it and we want it to be performant. In fact, we want to have a similar development experience as what we would have when working with a framework.

Here’s our tech-stack:

  • TypeScript

  • HTML

  • CSS

  • Git

  • Npm

  • Jest

  • eslint

  • Webpack

Now, you might think: 'Cool, but in the interest of keeping things simple, do we really need webpack?'. Well, we use webpack for a couple of reasons. Firstly to compile our TypeScript. Secondly, to run a development server for local development and thirdly, to bundle our files into a single .js-file to make our app perform better. Technically, there are a lot of tools that can do those things too, but this is an easy solution.

extra features
  • Will compile to ES6 javascript

  • ZERO production dependencies

  • Unit tests will NOT be included in the bundling

  • Contains partial browser CSS reset and included a font

  • contains a file to keep notes

Blood, sweat and tears

Getting all this to work wasn’t as simple as it seems. I wanted it to be as simple as possible, but achieving mimimum simplicity turned out to still be complex, considering my requirements.

My goal was to build a simple app to practise writing in a functional style. Therefore, I wanted the code structure to be simple, so I could focus on the code. And I didn’t want to include a framework, because I wanted to write the entire app functionally.

I started off with just HTML, CSS and a single JS-file. But as the application grew, so did my requirements for how I wanted to work with it.

serving files

The first thing I ran into was serving the files with a dev-server. The easiest solution I know to use a dev-server was by using the npm-package: http-server. Unfortunately, the server didn’t work because I used <script type=module> and downloading all the files separately resulted in a mime-type problem. My JS couldn’t be served through http-server. This wasn’t a problem I wanted to solve by myself, so I tried copying the code for a node server someone posted on the net. This node server was able to handle my problem and the code was served nicely.


When I wanted to write some unit-tests, I ran into some other trouble. Apparently neither Jasmine, nor Jest is able to handle the ES6 modules/imports (which I was using happily). I had to implement Babel to convert my code to es2015 code and I tried to implement webpack to run the babel transpilation. After some struggling I figured out I could do the transpilation without Webpack and I finally got babel and jest to work together. I finally had my unit-tests, yay!


Later, I wanted to convert the entire project to TS and the problems I solved simply returned. The upside was that I could simplify my build tooling, since I didn’t need Babel anymore. Transpiling all the code from TS to JS wasn’t very difficult, but now, my unit-tests wouldn’t run anymore…​ When writing TS imports, you can say you want to import a file with a .js extension or a file without extension. TS will not rewrite your import file extensions from .ts to .js. This also presented a problem because my unittests couldn’t find the .js files and my server couldn’t handle the files without extension. I tried out a lot of angles on the problem, but had a hard time solving it.

Luckily, I stumbled upon a working, simple webpack configuration that would work in my project as well. This DID solve my problems because it enabled me to not have those MIME-type errors when serving files, allowed me to run tests with Jest and since it bundles all files to a single .js file, I don’t have to specify .js in the imports of my .ts files anymore. In the end, just adding webpack (the right way) would have been fastest.

Because it took me so much time to get this right, I forked my application and made a template project out of it. That’s the project you can find here. Feel free to fork it.