PrimeCert v2.0

In this blog post, I talk about the journey of how I made my first FastAPI / Postgres / Svelte project incrementally as something to keep me busy in my numerous train, bus, and carshares these past few months. It felt like a dev’s version of JetLag: The Game to be honest.

I used to try to work a little bit on the train but I wasn’t sure of our work-from-anywhere policy anymore. Not wanting to get in trouble for working on the train and potentially ending up with some insurance or security issues, I eventually chose train rides as the time to work on my side projects because… well… I wont have any insurance or security issues if something goes wrong. These train rides were outside of office hours or when I was on leave anyway, so it is my me-time in any case.

What did I work on that needed so many train rides?

PrimeCert

I made PrimeCert as a response to all those own a star, own a planet and own an NFT websites. The twist, of course, is that you can own a prime… certificate. What exactly is a prime certificate?

What’s a Primality Certificate?

A primality certificate is a concise and easily verifiable set of data that confirms a number’s primality.

Basically, you give an integer to an algorithm. The algorithm works hard (and possibly for a long time) to give you a set of data. This set of data is the key to proving to other people that the integer is prime.

Other people can do the verification themselves with less resources because there exists an algorithm to do so that is not as resource-heavy as the algorithm to find this data.

In both the old and new versions of PrimeCert, you will find the theorem in the primality certificate.

Now that we have that covered, how was the old PrimeCert implemented?

The 2022 Version

The old version of PrimeCert was created two years ago, with me not having a lot of modern web dev experience. So I self-studied most of it. The result was the following Git repository back then.

Node.JS

The previous version was a mess that used Express.JS as a backend as it was something I want to learn. The single major API endpoint was /generate-pdf, which basically took two arguments: name and number - the name of the prime and the prime itself.

Using LaTeX to make PDFs

As a mathematician transitioning to the industry, LaTeX was love and LaTeX was life.

I ran a 1GB TeX installation inside a Docker container to compile a PDF with Math equations and a custom font to make things look official. This seemed a lot of bells and whistles just to get a nice-looking PDF. But at this point, this was the best solution I had and I wanted this to be finished as soon as possible so that I can continue to job hunt and update my CV.

How To Generate The Data

The primality certificate data I have been talking about is actually generated by the primecert function of PARI/GP, an open-source computer algebra system that I have talked about before in previous blog posts. This primecert function was what I worked on to implement during the year between my masters and my PhD and I think is the most efficient open-source implementation that I know of.

For the old version of PrimeCert, I simply open a PARI/GP instance, run a few commands, and then save the results into a file. My Node.JS app will then notice that there is a change in the directory it is watching, and process that into a PDF. Looking back, it’s a miracle that it worked. But it did. And that’s step 1 for me.

Reception

Most of my friends were quite amused to name their own primes and get their corresponding certificates. Most of them did not have a favorite 19+ digit prime and simply copy-pasted one of the examples and made it their own.

However, they were eventually disappointed learning that there was actually no database keeping track of which prime is named which. So for example, if Francesco and Sergej claimed 18446744073709551629, then they would both have a PDF claiming it’s theirs. It’s as if I double-sold a prime, much like how an own a planet company might double-sell a planet.

We can’t have that! So I’ve always wanted to revamp the PrimeCert project in order to make sure that when a prime is named and claimed, no one else can claim it. The name stays (as long as it is reasonable).

The 2024 Version

It’s 2024 and I have transitioned again from a frontend to a backend role within my company. Instead of using React, I am using Python FastAPI in my day-to-day. I arrived in the middle of the project and there has already been a FastAPI project setup.

As my first try on this project was in Javascript, I decided to use this revamp as an excuse to try out starting a FastAPI project from scratch.

Python and C Working Together

As this is a project I’m doing in my free time, the first thing I did was to start a new FastAPI project and see if I could actually make it interface with PARI in a way more streamlined than the old version. If it were not possible, then I would have to fallback to the old version’s messy ways and this project would just end up me rewriting Javscript (ExpressJS) into Python (FastAPI).

I started by installing PARI/GP locally and finding the libpari.so file, a shared object file containing functions and routines written in C. That’s all fine and dandy. But we need a bridge from C to Python.

After a few Googling and ChatGPT-ing in the train, I stumbled upon ctypes. It is a Python package one can use to interact with C libraries. Perfect!

import ctypes
lib = ctypes.CDLL(lib_path)

A simple code such as the above gives access to any shared object file you want. That means I can access this primecert function from Python directly.

While I was quite happy and in a celebratory mood when I figured this out in a TGV (fast train) going back to Bordeaux, I did not actually do anything concrete to celebrate this finding because:

  • I was far away from the car which sold food,
  • The food was overpriced anyway even with the discount my Carte Avantage gives me.

At this point, implementing the rest of the backend was somehow straightforward. I implemented endpoints to generate prime certificates quite easily.

The next step was to have an actual working database. I’ve used SQLite before in other small projects, but I’ve never used Postgres. So, I thought I should try that out.

Postgres Database

With my previous SQLite and MySQL experience, installing and setting up postgres was relatively easy. Armed with DBeaver this time around, I was able to visualize the table structure more easily.

One culture shock I had using Postgres was that my installation had us make a schema first, before getting to a table? I honestly have not dug into this enough to understand it so contact me if you have an explanation. Or perhaps I’ll talk about it in the future when I eventually run into a roadblock that needs me to understand this part.

For what it’s worth, I got the basics of this Postgres DB setup down. And I could learn more if I wanted to go deeper. It took another two-hour train ride going home to Bordeaux in order to setup the communication between the FastAPI app and the database.

I did not bother with using an ORM for the moment to keep things simple, but I did take care to try to sanitize the raw SQL statements I am using to prevent certain security attacks.

The FrontEnd

I have used React and NextJS over and over and over again and so I thought it was time to try a new framework.

While Angular seemed to appear in a lot of job listings these days, I opted for Svelte for my humble project because I heard that it provided a better dev experience and to be honest, I’m actually quite curious about it.

Prototyping the Design

One bad practice I always do in personal projects is just have one main file have all the functions. That way, I don’t have to name new files, which according to tech memes is one of the hardest things about software development.

I did not bother using Figma because (1) of my artistic and design limitations. I am not a senior designer, much less a junior one. The time making a design would not seem worth it because it’s going to look bad or basic somehow. And (2) I could use HTML and CSS to prototype the app before writing the functions. Which is exactly what I did.

I was also lucky to have had this task while chaining trains, buses and BlaBlaCars on the way to a wedding in the middle of France. During my transfer times, I was imagining what the website would look like. And as soon as I sit down on the train or the carshare, I start coding it. I would like to dedicate this section to the death of my perfect 5-star BlaBlaCar rating. I did politely ask the driver if I could use my laptop during the carpool and they said it was fine. But they gave me 44 stars anyway, bringing my rating down to a 4.94.9! The horror! I might have to put “might code in the carshare” sometimes to tamp down expectations.

On the other hand, Svelte gets a 55 rating for prototyping because I did not have to jump around from a .svelte file to a .css file every 55 or so seconds. Everything was in one file. It’s a personal preference, but I like it so much. Don’t worry, I did refactor everything into several components eventually!

Adding Functionality

For the first release of this app, I decided it will be desktop only. I didn’t care about the mobile version. Why? I thought that since we would mostly be dealing with horizontal pages due to the 50+ digit numbers we will be encountering, it would be more practical to do it on a desktop.

Fun fact: I did eventually implement a mobile version (via CSS Media queries) while on a Eurostar from the Netherlands to France! And it was a relatively easier refactor that I expected!

Anyway, once the prototype for the desktop app was done, I started working on the functionality!

It’s a nice breath of fresh air that Svelte does not need me to micromanage states and does everything itself. Introducing contexts was also a breeze and felt natural. There was some culture shock with the syntax, but most of those were easy to get used to.

Another train ride after, and I had my first version ready. Time to see if my basic “devops” skills are still sharp.

Deploying

Two years ago, I would have been super nervous dealing with a docker-compose and a Caddyfile. The thing about writing these configuration files is that one doesn’t really get a lot of practice because it’s usually a one and done situation for most projects and my lack of experience has made me a little bit nervous.

Thankfully, I have compiled some Docker commands that I use into a blog post and I had an old Caddy file that I could base on. Hooray for having a blog.

I’ve learned it’s good to use ChatGPT to not have to start from scratch and that was exactly what I did. Fortunately, the train I was taking this time around was passing through an area with relatively good connectivity so I manged to get ChatGPT’s answer in a relatively short amount of time.

From ChatGPT’s suggested Dockerfile, I learned some new things (that I am not going to list down now) but of course I knew I still had work. I had to understand every line and check whether or not I need it, and whether it is correct syntax or a hallucination.

I was pleasantly surprised how fast I managed to set things up this time around, given that it was the first time in a long time that I am using a docker-compose.yml to run three different interconnected containers — the frontend, the API backend, and the Postgres DB.

The only hiccup I can remember was CORS. Of CORS it’s CORS. FastAPI had a quick way of dealing with that and I am thankful!

Conclusion

It’s great to have my old version in Github to see how much I’ve learned in front, back, and devops these past few months. I would certainly look back into these posts during particularly challenging days as a reminder that yes, I managed to grow and upskill despite it being incremental day-to-day improvements.

To conclude, I note that I wrote this blog post was also written on 20 july 2024. So, to remember this, I declared an integer which repeated 20240720 a bunch of times to be called the Blog Post Prime. While doing that, I did find a small bug that I would probably be squashing… hopefully during the next time I travel.

But for now, please enjoy version 2.0.2 of PrimeCert.