1 February 2021

From now on, you can pay your fines online for the City of Ghent

The transition from paper to digital still keeps on going. The same goes for paying fines. During the first year of Element7, we’ve developed invoice.gent for GDW Gent.

We’d like to share some details about the technical details, and the lessons we have learned along the way.

What exactly did we make?

invoice.gent is a website for the bailiff’s office GDW Gent in cooperation with the city of Ghent. It allows you to find more information about your unpaid dept to the city of Ghent. Debts can be paid directly via the website.

Bauke van der Laan helped us to figure out what the best user experience would be for the customer and created a nice and clean user interface for the site.

To come up with the right flows, we co-operated using Excalidraw. Afterwards the Excalidraw mockups were converted to Figma into a visual design of the User Interface.

Preview

The website of invoice.gent

For the full version, see invoice.gent.

Architectural overview

The following image shows how we have architected the application.

Architectural overview of invoice.gent

Technology Stack

Frontend

The public facing website is made using Hugo and some vanilla JS. All content is stored in Markdown files. During the deployment fase, Hugo generates only static assets which are published to S3 and distributed by the Cloudfront CDN.

Backend

There are four API endpoints in total. Every handler is a separate Go module served by AWS Lambdas. We use DynamoDB to store and share payment details between different endpoints.

Payments

Mollie allowed us to easily accept online payments. Their developer docs have been proven very helpful throughout the process.

At the moment, we support payments for Bancontact, bank transfer, iDEAL and SOFORT Banking.

CI/CD

The code is hosted on a single repository at GitHub. Commits on the main branch are being picked up by AWS Amplify. Amplify will verify the code by running the unit tests. When the test are green, the deployment will proceed.

Learnings

Hugo allowed us to separate the content from the codebase. It is blazing fast and easy to install.

Although we considered using React, in the end we didn’t use a Front-End Framework at all. Since there’s no state that is shared between pages - and the logic on every page was manageable. This saved us from having to setup the development tooling for a Single Page Application.

Golang allowed us to get up to speed quickly, but that doesn’t mean we did not have some hurdles along the way we had to overcome.

  • The AWS Serverless Application Model (SAM) CLI has some shortcomings. There’s a 128kb payload size limit when invoking an event.
    So we had to test this using a small dummy image. When running the handler on AWS, the limit for the payload is 6MB. We might improve this in the future by uploading assets directly to S3 instead.
  • The second learning is about the boundary of our endpoints. We might be better off using a single handler for all four endpoints. They all deal with payments and share at least some logic. So having them separate feels odd afterwards.

AWS Amplify runs the CI jobs. Unfortunately, the result is not visible on GitHub. We ended up using GitHub actions for the same CI jobs. This means we have duplication for our CI logic / configuration.

The verdict

People will benefit from the streamlined flow of paying their fine online. However, most of them will never know the details of how the site was build.

We learned a lot during the process of creating invoice.gent. If you’re interested in working with us on a potential project, do not hesitate to reach out!