Home

August 1, 2024

Rewriting LIT using SvelteKit

I rewrote the LIT website and contest platform from scratch using SvelteKit, Tailwind CSS, and Lucia. I also replaced the Standard Round grader and deployed the website, grader, and database with Docker.

Why

The codebase I inherited from CodeTiger (orz) was unfortunately really difficult to maintain. The entire application code was written in one file with 1200+ lines of JavaScript: no type safety and unclear response data emitted by socket.io. I also much preferred using REST instead of socket.io.

The authentication system also needed much improvement, because users were only assigned numbers to sign into their accounts, which was surely not secure.

How

Early Library Changes

I began work on the new LIT website in August 2023 and made my first commit in January 2024. I initially used DaisyUI, but I overhauled the entire site to use shadcn-svelte a week later. I had followed the progress of the radix-svelte project, then melt-ui, and finally shadcn-svelte.

Authentication

I found lucia while researching authentication for SvelteKit on the Joy of Code and Huntabyte YouTube channels, both of which are great Svelte resources. In May 2024, I upgraded to Lucia v3, which deprecated the Key model. I use Prisma and Lucia’s Prisma adapter.

Teams sign into a team account via username/password. In Prisma, each account is connected to a Profile model (one-to-one), which is then connected to all the CTF and Standard Round submissions. Each submission is connected to both the Profile model (many-to-one) and the corresponding challenge/problem (many-to-one).

Prisma Setup in Docker

I was finally forced to learn Docker in the month before LIT just to deploy the website, grader, and database services. Deploying with Docker required that the database be seeded after the Prisma client was generated and the database synced with the Prisma schema.

package.json

"scripts": {
  "start": "pnpx prisma db push && pnpx prisma db seed && node build"
},
"prisma": {
  "seed": "pnpx tsx prisma/seed.ts"
},

Note that I used tsx instead of ts-node due to one of these errors (I don’t remember which):

CTF

Instead of a JSON file, CTF challenges are stored in the SQL database, allowing admins to quickly update challenge descriptions and settings. Dynamic scoring is achieved by assigning each challenge a point value, which is updated whenever a correct submission is received. Therefore, wherever a team’s score appears (e.g. scoreboard, team page), that score is recalculated on each page load.

Standard Round Grader

The old LIT grader was the camisole judge. We ran into some issues during the contest in which this judge would randomly die, sometimes at times when no organizer was awake to restart it.

I replaced this with a new grader and used Docker so that the service would have healthchecks and auto-restart to ensure minimal downtime during the contest.

Wrapping Up

So far, I have replicated all the functionality from the old website, and I will soon be looking to add new features that make the organizers’ jobs in prize distribution easier. I will also experiment with some features for the contestants to make the contest more fun and to have more data sources to use in our T-shirt designs. In LIT 2023, the shirt design was based on the CTF challenge difficulties.