Open to work

Full-Stack
Engineer

I want to know why it works, not just that it does.

Kalle Spets Blomberg. BSc in Computer Science & Engineering from KTH. I particularly like building web apps end to end. Interface, API, database and deploy.

Kalle Spets Blomberg
Shall We Read interface

Shall We Read

Get A Personalized Recommendation

A Korean-language book recommendation quiz that asks what you want to feel or gain from a book, not just which genre you like. It has reached up to 40 daily users and earns through Coupang affiliate links. Built solo as an experiment in agent-driven development.

  • Claude Code
  • Next.js
  • React
  • JS
  • TailwindCSS
Live demo

Shall We Read is a fun book recommendation service. You answer a set of questions and get a suggestion for what to read. Some of the questions are simple, like which genre you prefer, but others ask for deeper, more specific information, such as what you are looking to gain or feel when reading a book. This was an intentional design decision to set it apart from the more generic book recommendation services that already exist.

The app has reached up to 40 daily users and has generally received positive feedback. Users commented things like “fun idea!” when sharing the website on Threads. Their main concern was the small catalog of books. This was very much expected, as I intentionally took a small set of books for the first development cycle. The second cycle prioritizes refining the recommendation algorithm and adding a larger book catalog. As of this writing, the second development cycle is still in progress.

The business model is based on Coupang affiliate links. Every time a user buys a book through a recommendation, I get a small percentage. Until you are a Coupang partner, the affiliate links must be generated manually, which also makes it harder to add a large set of books from the get-go.

Workflow

I developed the website independently and used Claude's Opus 5 model to power a lot of the implementation. I also took the opportunity to experiment with agentic workflows, using Claude Code's GitHub Actions integration to have it work on issues directly through GitHub. I also experimented with different popular sets of Claude skills, such as Matt Pocock's skills for closely guided agentic development.

The hardest part of developing this app was getting aligned with the agents. When pivoting quickly on ideas, the agents had a tendency to keep old logic and ideas, which hindered the accuracy of implementing new ones. For example, at one point an agent failed to properly change the recommendation algorithm, despite me explicitly telling it what to do.

My current solution is to manage the context carefully: create a larger plan with a few planning agents, then implement the plan one step at a time with a clean context. Implementation can of course be done concurrently, for example with GitHub workflows, unless there are blocking issues.

Recommendation logic

The recommendation logic is based on filters and a scoring process. Each book is associated with a fixed set of data. Here is an example:

{
  title: '죽고 싶지만 떡볶이는 먹고 싶어',
  author: '백세희',
  year: 2018,
  genre: ['essay'],
  ratings: {
    need: { comfort: 3, fun: 1, knowledge: 1, growth: 1, trend: 1, habit: 2 },
    priority: { easy: 3, depth: 1, bestseller: 3, happy: 1 },
    topic: {
      money: 0, relationship: 1, career: 0, mindcare: 3,
      society: 0, science: 0, history: 0, selfunderstand: 2,
    },
  },
  trendRatedAt: '2026-09-24',
  avoid: ['heavy'],
  difficulty: 1,
  length: 'short',
}

Genre is one example of a filter: it narrows the catalog down to books in the genre the user selects. Ratings and topic contain the values used in the scoring process. A score is calculated for each book that passes the filters, based on how the user answers. Books with higher numbers in the ratings and topics the user preferred get a higher score, and the book with the highest score is the top recommendation.

Run A Way interface

Run A Way

Measure your route

Run A Way lets you manage your running routes. You draw your routes by clicking on the map. It then measures the distance and the calories burned on the route. I have used similar websites, but always thought their interaction with the map was lacking, so I created my own with a smoother user experience.

  • Next.js
  • React
  • TypeScript
  • TailwindCSS
  • Material Tailwind
  • Leaflet.js
  • OpenStreetMap
Live demoSource
How it's built
The app is written in Next.js, TypeScript and TailwindCSS. It uses the Leaflet and React-Leaflet libraries to access OpenStreetMap which is a free to use map api. I also used Material Tailwind to create the buttons.
What was hard
React-Leaflet and Leaflet is not very well documented, so it was a hurdle to just get it to work with Next.js. It turned out that I needed to use a dynamic import of the map and had to render the map lazily, fundamentally due to compatibility issues with Next.js.
What I learned
The biggest takeaway from this project is integrating different js libraries together that don't by default work well together. I was for example required to downgrade the react types dependency to a previous version to be able to use Material Tailwind's react components. In these situations it becomes clear that a good fundamental understanding of Node, React and how modules work together is super important.
Would You Rather - Programmer Edition interface

Would You Rather - Programmer Edition

Find your programmer personality

A Game where the user is presented with two scenarios and has to choose which one they prefer. After they choose they get presented with what percentage of people picked the different choices.

  • React
  • TypeScript
  • Go
  • Docker
  • CI/CD
Live demoSource
How it's built
The app has a frontend written in TypeScript, React, TailwindCSS. And a backend written in Go and SQLite. The backend provides scenario pairs. And exposes endpoints for fetching random scenarios without providing the same scenario twice until all scenarios have been seen. Both the frontend and the backend were fully designed and implemented from scratch. The frontend, other than the game, allows the user to change the color theme, which I mainly made for easily picking my favorite colors during development.
What was hard
The most difficult part of developing the backend was designing the api and preventing the user from fetching the same scenario twice. However, most of the time was spent on the frontend where the biggest hurdles were dealing with the different game states. I had to make intricate changes to the UI depending on what state the game was, which proved more difficult than my first estimation. This was also due to extending the visual feedback in the game in the middle of development rather than planning it from the get go.
What I learned
This app taught me how to go from zero to a working application. Everything, from conceptualization to design, development pipeline, implementation and hosting was all done by me. It taught me not only lessons in programming, but also lessons in developing from a user's perspective. Watching someone with a marketing background use the app showed me how differently a first-time user reads an interface, and several UI decisions came directly out of that feedback. Furthermore, I think the biggest lesson I learned was in the development process. It was my first time creating a CI/CD pipeline with GitHub Actions for a personal project.
Chatapp interface

Chatapp

Stay Connected

A chat application inspired by Discord. It uses Node.js, Express, Socket.IO on the backend and React with create-react-app on the front end.

  • React
  • JS
  • NodeJS
Source
How it's built
Chatapp consists of two parts: A frontend build with React and TailwindCSS, and a Node.js backend using Express.js and Socket.io. It has no persistent data storage, all data, such as created users and message sent are handled in memory.
What was hard
The most difficult part of the project was making sure all communication between server and client was handled correctly and that the representation of data between the server and client were compatible. There were multiple times where I had to rethink the way I handled certain requests. This resulted in me building a strong set of unit tests to support my development of the server.
What I learned
The big lesson I learned creating this project is the easy win of making a strong set of unit tests for data transformation on a server. It was a start of a workflow shift, where I now always try to write tests along with my server code and implement it in a way that is easily translated into unit tests. This has saved me a lot of headaches when something suddenly does not behave as you expect.