Insights into the development of an online reservation system

Inserve
6 min readApr 18, 2022

Building an online platform is not easy, building a platform as a sole developer that is highly scalable and processes interactions in real time is even more challenging.

What I’m talking about?

Inserve. It’s a free reservation system with an interactive floorplan tool based on an unconventional technology. I’ll go into more detail about it below.

So what’s the tech stack?

During development, a few things were very important. First of all, the technologies used had to be simple and quick to learn. I am the only developer and have limited time to work on Inserve (that’s one of the reasons why it took almost two years to finish). Another factor was scalability and costs. As it grows, it shouldn’t break the budget.

A quick overview of all used technologies/tools:

Backend

  • Firebase (Firestore, Cloud Functions, Firebase Authentication, Firebase Storage, Firebase Hosting)
  • Google Maps API
  • Axios
  • SendGrid

Frontend

  • Vue.js (Vue 3, Vuex, Vue Router, V-Calendar, Vue I18n)
  • d3.js
  • Luxon
  • Design tools (Font Awesome, Undraw, Unsplash)

Backend and database

This was an easy choice. I chose Firebase for all backend related stuff, because it met all the previously discussed requirements. It’s highly scalable and the costs are transparent. But one of the most important things was the wide range of learning materials.

And it has really cool realtime capabilities. For example, when a guest makes a reservation, it’s instantly shown to the business owner in their monitoring tool without much code involved. It’s that simple.

There is actually not much going on in the backend. The serverless backend logic (Cloud Functions) essentially just validates the client’s requests and stores it in the Firestore database. Here and there I need to call the Google Maps API (with Axios) to find out the time zone and coordinates of an address. More complicated is the code that validates the seat selection of a reservation. For all of the email notifications I use SendGrid.

Frontend

For the frontend I used the framework Vue.js. The only valid reason was that I already had experience with it. I could easily use React for this project, it wouldn’t hurt in any way. But I would lose a lot of time learning it.

The development of Inserve was happening just as Vue was making the transition from Vue 2 to Vue 3. When I started Inserve, Vue 3 wasn’t even out yet. After Vue 3 was released, I decided to upgrade, so a major refactoring was necessary. But until today I don’t really take advantage of the Composition API, because there is still a lot of left over from Vue 2. Eventually I will change it, but that will take some time.

A reservation system is very dependent on time and date. That’s why I used Luxon for formatting all time and date outputs. Regarding the design, I used Font Awesome for the icons, Undraw for some really nice illustrations and Unsplash for images.

As you can see, these are more or less obvious technical choices that you can also find in dozens of other blog posts. However, one thing that is quite different is the floorplan tool. This tool allows guest to make a reservation by simply clicking on the desired seat on a 2D map. This is by far the most difficult thing to develop, which is why it took the most time.

How did I build the floorplan tool?

Let’s talk at first how I didn’t build it. The very first thing that came into my mind was Canvas. It seems like the obvious choice. It’ s performance with a lot of objects is much better than with SVGs. Only the fact that everything inside the Canvas isn’t part of the DOM was a real drawback. But at first I thought that wouldn’t be a big deal, so I looked into many Canvas libraries.

Quickly I found two perfectly suitable libraries: Fabric.js and Konva.js. I decided to go with Konva because I liked the documentation a bit more.

At first it worked flawlessly. I could easily create some simple rectangles representing tables and interact with them. The functions to change the size and position were already in the library. So I’ve created a solid foundation on which I have many different items that can also “snap” onto a grid layout.

Styling non-DOM elements

All of this was fine, but when I started styling these items, the difficulties began. Because things inside the Canvas are not part of the DOM, all of the styling had to be done through Javascript. That’s not necessarily a problem, but it makes things pretty difficult if you prefer styling through CSS. And it was cumbersome. Just to create some box shadows required a relatively large amount of code. We don’t even need to talk about animating the shadow. It was way to much.

I also planned that the floorplan should use the theme of the webapp. So if I add a darkmode, the floorplan should also be dark. With CSS custom properties this is a matter of seconds, but with Canvas it’s more complicated.

These and a few other minor things caused me to rethink my Canvas strategy. So I started looking into SVG, focusing especially on the performance aspects.

First I made a simple SVG with some rectangles inside. Immediately the question arose, how can I interact with this SVG? How can I add elements, listen to click events and so on. I had two choices, either use Vue for this or use a library that already provides tools for interacting with SVGs. I didn’t want to use a library, so I tried Vue itself, but I quickly realized that the big features like drag-and-drop are very time-consuming to implement.

d3.js as a rescue

So I looked into SVG libraries. Immediatly the library d3.js popped up. It’s more of a data visualization library, but it offered all of the features I needed. And it was very well documented. So I chose this technology and completely rebuild the floorplan. Surprisingly, replicating the features I already had with the Canvas-based floorplan went faster than I thought.

Adding, removing, styling tables and seats was done in a few days. I especially saved so much time on styling because I could use CSS. Just amazing!

But this route wasn’t without problems

After the floorplan became more sophisticated, performance issues became something I had to deal with. I saw that adding more than 100 tables was problematic. Why? A table consists of more SVG elements than you might think. For example, a table with 6 seats consists of 24 elements. And believe me, that’s as low as I could get it to support all the features. So with only 100 tables, we are talking about 2400 DOM elements that need to be rendered.

After some testing, I found that most phones can display 75 tables with decent performance. Hence, I have limited the maximum number of tables to 75. I don’t see this limitation as a problem because if more tables are needed, splitting them into multiple floorplans is a good way to organize them.

I also tried to improve the slow initial load time by using staged rendering. During the initial rendering of the tables, only the rectangle of each table is displayed. After a few milliseconds, all other elements within each table are rendered. This has had a very positive effect on initial loading speed.

What would I do differently?

I would immediately go with SVG instead of Canvas for the floorplan tool. But I’m not really unhappy about the way things went because I learned a lot about Canvas. As for the frontend and backend, I’m very happy with the decision to use Vue and Firebase. I wouldn’t change that at all.

Closing thoughts

It’s been a great journey developing the whole project myself, and I’ve learned a lot along the way, especially in dealing with SVGs and Firebase. I hope I could give you some good insights into the development of Inserve. If you have any questions, feel free to ask them in the comments!

--

--

Inserve
0 Followers

Free Reservation System — A revolutionary reservation system with an incredible seat selection tool based on floorplans.