Summary: I built this bikes page using SvelteKit. Below I go into details about all of it.
I've been slowly getting back into writing code, mostly for fun, and not building anything serious yet. To start out with something fresh, I wanted to try SvelteKit. It's been on my radar for a bit and usually I default to Next.js for any project but for this one, I had very specific requirements which Svelte was perfect for:
- Little to no configuration
- Builds as a static site to Github Pages
- Data is loaded once, either on the fly or pre-build
- No user-auth
- Has a build system like Vite or similar
These were all possible with Astro as well but I didn't want to go down that route this time, I picked Svelte for its super lean single file components.
From this, the project I wanted to build became pretty straight forward. I built a bikes page (see here) that I wanted to use as a place to track my bikes, their components, related events (like maintenance, breakdowns, etc) and show the per-mile costs.
How I built it
The data for this is straight-forward, see the Prisma schema file for more details. It stores the following:
- Bikes and their details like miles ridden, when I bought it, how much I bought it for, and a photo of the bike.
- Components are only tracked when new ones are added, e.g. an upgrade is made or a replacement is added due to the stock component breaking down.
- Miles are added as mileage updates whenever I get a chance to update these. Fortunately, all my bikes have odometers installed on them so it makes it pretty easy to track that. I opted to not used Strava since not all my riding is tracked on there. And for my electric dirt bike, no Strava data is available.
- Events are arbitrary updates like buying the bike, repairing it at the shop, performing a cleaning or maintenance, and anything of that realm. My old bike (Big Red) has an event called "Sold" that I will use to track sold bikes.
Displaying the data
Using Prisma and SQLite, I decided to keep the data within a file that will be updated through Prisma Studio. With that removing the need to build a creation UI, I was left with how to display the data. I chose to use a JSON file that the UI can display. Not all the data in the database is output through the JSON file as it's not necessary to do so, one of this is the mileage updates, only the latest mileage update is of use for each bike. The script used for this was written mostly by ChatGPT and I did some massaging to get it working.
I used Tailwind with Svelte to make the styling process plain and simple. It isn't much of a UI besides a few cards and some border-radius added to them. The UI currently only shows the bikes, but I will add in the events and components eventually as well.
Deploying a static website
Instead of relying on something like Vercel to deploy a full stack app, I went with Github Pages because at build time (within Github Actions), I build out a static version of the app and export all that to a
build directory, this eliminates the need for runtime JS that Svelte would need to run each time the website was visited. This also constrained me into thinking about how to have the JSON file available all the time and I just went ahead and used the above script for exporting the data as a static file and then when it's built, Vite bundles it alongside the rest of the app.
If you take a look at my bikes currently, Big Red has the lowest per-mile cost which is pretty impressive but it also doesn't include some of the accessories I had bought for it since I don't remember them all. For the newer bikes, there's almost every component accounted for and the prices aren't too bad. For the electric dirt bike, there's a long way for it to go before it gets close to the other bikes in terms of per-mile cost. I hope to use this per-mile cost to determine just how much a bike is used compared to my car.