Structuring the App and UI Scaffolding

This is Part 1 of an article series that documents the process of building the Triple Tee App.

May 02, 2023 | 5 mins read

Let’s Give It A Name

I haven’t confirmed the name of the app that I was going to build, but I can’t do anything without a name for the code repo, so for now I’ll codename it “Triple Tee App”. Where do the 3 T’s come from? It’s “Tag”, “Transaction” and “Tax”. Not very creative, isn’t it?

If I can’t think of a better name than this, I might just end up sticking to it, because thinking of a name is a very brain-damaging activity. (laugh)

Can’t leave the name blank forever, right?

Setting Up The App Structure

It turns out that figuring out the app structure is not so simple, because JS.

Spent about a day setting up the structure of the repo so that the server, client and Electron wrapper all work together properly.

The first thing I learnt about from this exercise was that there’re currently 2 ways to modularise JS modules:

  • CommonJS: default of Node.js
  • ES Modules: standardised approach supported by major browsers

I will spare you the details of the difference between the 2, because there are already a lot of articles out there for that purpose. But I want to talk a little more about how I dealt with the mix of use of both approaches in my app.

First of all, although it was recommended that we use ES Modules for a new project, in the end I had to go with CommonJS because Electron has no ESM support. There’s a library called build-electron I stumbled upon which can help build the main.js and preload.js of Electron from ESM into CommonJS for Electron to run the app. But just by using this tool, I had to include 3 other dependencies and complicate my build pipeline. I decided to keep it simple and stick with CommonJS.

Then there’s the server-side code, where I use Express.js as the framework. Before I learnt about CommonJS vs ESM, the tutorial I read about Express.js is in CommonJS, so I already started working on some scaffolding in CommonJS. Since Node.js supports CommonJS by default, I didn’t think of changing it to ESM because then I had to change all my existing code to use ESM syntax.

Finally, I use Vue.js for my client-side code. Now, Vue.js uses ESM by default, and I had created a scaffold app and successfully run it together with my Express.js server code. It turns out that Vue.js uses Babel under the hood to compile ESM to CommonJS anyway.

So in the end, I just decided to stick to CommonJS for my server code and Electron wrapper, and use the default ESM for client code. It’s a little confusing if it’s a single person coding both server and client, but if we think about it from the point of view of having a backend engineer code the server, and a frontend engineer code the client, then there’s actually no issue with it, I think.

Of course I still wish to standardise the modularisation of this app to ESM, but if I had continued to dig deeper into figuring out how to make it work, I think I wouldn’t be able to finish the app within the timeline. Sometimes there’re just compromises to be made in order to actually achieve a goal, otherwise the idea will just remain an idea without something concrete to show for it, right?

Here’s the end result of the folder structure after considering the modularisation approach.

  • client: This is where the Vue.js code sits.
  • out: This is where Electron will build the app distributables into.
  • public: This is where the Vue.js assets will be built into and served by Express.js.
  • server: This is where the Express.js code sits.
  • common.js: This is where I write some shared functions and constants to use across the app.
  • main.js: This is the entry point for Electron to run the app.
  • preload.js: This is where Electron run some code before rendering the app.
  • server.js: This is the entry point for Node.js to run the server.

Monorepo with client, server and Electron wrapper.

Some Form Elements

Now that the most important part of setting up the folder structure is out of the way, it’s time to get down to writing the code for the app.

To know that I’ve made some progress, I started working on the most obvious thing first: the UI elements, so that I can see it concretely materialise before my eyes.

Spent about half a day building the input and button elements using Vue components. This time I decided to not use Vuetify as a challenge for myself to style my app without existing framework, and also I want to reduce the bloat of my app as much as possible by using as few dependencies as my skills can allow for.

Not too bad, it’s quite close to what I designed in the wireframes.

That’s All For Now

That’s the result after 2 days of work, I think I’ve made pretty good progress so far. Hopefully from now one I don’t have to deal with anymore framework related issues, and can focus on building the app itself.

Stay tuned for more updates!