A complete scheduling solution for restaurants
A screenshot taken from the ShiftR web application, it displays a login modal where the user is asked for their email and password to log in.  The modal also displays the logo of the restaurant and an option to switch between the service- and kitchen department within the restaurant. A screenshot taken from the schedule editor within ShiftR, it shows a table-like view where each day is represented as a column while the rows represent an employee.  Some of the cells are filled with times, representing the start time for a given employee at a specific date.  Other cells contain an 'x' or 'v' indicating that the employee cannot work or has taken a free day, respectively.

A new version of the scheduling system is in development using a different technology stack (Ruby on Rails and PostgreSQL). Some details about the new version are discussed in the last section. A full update to the page will be made once the new version is released.

Before I started university I used to work at a local restaurant where the entire process around the schedule took part on paper. Modifications to the schedule were made by crossing out old start times, availability for all employees was written down on a single physical piece of paper, and hours worked were manually calculated and aggregated through a daily print out of a day-list.

With my experience in building web applications I discussed the option of building a custom scheduling solution for the restaurant with the owner of the restaurant. After some initial sketches and discussion I was allowed to take some shifts to work on a prototype. This project was the first real world application that I would build for people to use.

Left side: A screenshot of a day-list, containing a row of employees working from opening until closing time. For each employee the screenshot shows their start time, end time, and total hours worked. Right side: An small snippet from the weekly schedule overview. For each day a column a list of employees combined with their profile pictures and starting time.

The application itself has quite a lot of functionality, but the main features are:

The process

The entire project has been built from the ground up by me, including the design. I gained deep exeprience with different concepts such as authentication, mobile web apps, how to build an API, how to interface with other applications, and how to manage and update state in a frontend VueJS application.

Throughout the development process I worked iteratively with the restaurant owner and, once we had a working prototype, with other employees to test and improve the application.

After completion (version 1.0.0) I maintained the application with several updates where I fixed bugs, implemented the ability for employees to exchange their shifts, and improved performance.

A screenshot showing a time-off request by Jeroen for a little more than a week in March. Logged in as an admin the user is able to accept or decline the request. In addition to the request a calendar is shown, highlighting the days for which the employee requested time off.

Over the years, developing and maintaining this product, I have learned many valuable lessons. I experienced the concequences of technical debt, the advantages to testing my application, the trade-off between building additional features and the complexity in maintenance, and the architectural cost of certain decisions such as not supporting multi-tenancy at the application layer. In addition to these technical lessons I also worked with the actual users of the product, learned how to translate their requests into designs, iterate upon them, and finally translate the design into working application code.

A highlight

One of the most challenging aspects to implement was the authorization system, after working on the authentication I needed to be able to create different roles for different types of employees. This specific restaurant required 4 roles:

As I planned to launch the system for different restaurants I decided to take a variable route such that I could make changes to the permissions setup on a per-system basis.

I annotated every API function with a required permission that the logged in account needs to be able to use it. This allowed me to define roles, each only with the permissions for the calls they are allowed to make. Employees are assigned a specific role and therefore inherit all the permissions from that role. This system made it easy to add additional roles where needed or to modify them for a different instance of the application.

New Version

As this was the first project I completed at this scale of complexity, I made early mistakes in the architecture of the system. Most importantly the system does not scale easily to multiple restaurants, it requires a separate instance of the application for each different restaurant. While I was able to automate the setup of a new system using Docker it still requires manual work.

In the new version I make use of multi-tenancy, a design pattern that allows the same system to handle separate, software isolated, workspaces for each restaurant.

Left side: A screenshot of the new availability tool, displayed as a calendar with every week on a new row, every date that has been marked available is marked in green. Top Right: A screenshot from the new schedule editor, displayed as a table with days for columns and employees as rows. New in this version is the ability to make (unpublished) edits to a published schedule. Bottom Right: A screenshot of the published schedule, as seen by employees for two separate days.

The new version does not include additional features over the original, even though I have a lot of ideas, I am building less, such that the supported features get the attention they deserve. The underlying thought is to build half a product, not a half-asssed product.

I am building the new version on top of Ruby on Rails, a framework (built on top of the Ruby language), this has been my framework of choice for over a year now. In addition the latest developments in the world of Ruby such as Turbo and Turbo Native allow the creation of interactive server-side rendered web applications and native mobile applications, respectively, while staying (mostly) in Ruby world.

The server-side rendered nature of Ruby On Rails eliminates an entire workload from the project, as well as reducing the required maintanance required in the long run. There is no need to create a client-side data model, handle client side data storage and updating (using a framework like VueX), or to maintain a separate pipeline to build such a frontend application.