Projects

Websites for small businesses, clubs, and the tools I run myself.

Fast, simple sites that are easy to update. I build them, host them and look after them so the owner does not have to think about it. Started with my dad's business. Now it is a thing I do. Below that: the software I built to keep all of it running.

Client websites

garageport.se
Garageport.se start page: headline, door gallery, quote form and the 10 year guarantee section

Garageport.se

2023 · Live, later moved off the domain

Client: local garage-door installer, ConDoor reseller

A local garage door installer needed more than a Facebook page: what he sells, why it is good, and one obvious way to ask for a price. Three pages. The start page with a photo gallery, a three-field quote form that lands in his inbox, and the 10 year guarantee spelled out. A Portar page that walks through the four ConDoor series, one photo and one paragraph each. A Brochyr page with the Swedish and English PDF.

  • 3 fieldsquote form, replaced phone tag
  • 4 seriesHigh, Design, Wood, Top-Line
  • 1 containerbuild → deploy
  • Vue
  • JavaScript
  • HTML · CSS
  • Docker
garageport.se/portar
Portar page: four door series in alternating photo and text rows
Portar. Alternating photo and text rows, one per series. The photos are the product, so they get half the width.
garageport.se/brochyr
Brochyr page with Swedish and English PDF downloads
Brochyr. Two PDFs, two buttons, cover previews. Nothing more was needed.
Start page on a phone
Portar page on a phone
Brochyr page on a phone
On a phone. Rows stack, the form goes single column, the nav folds into a menu. Most visitors arrive from a phone.

Asarums Bangolfklubb

2026 · In progress

Client: minigolf club in Asarum, Blekinge

Blekinge's largest minigolf facility, three 18-hole courses, run by volunteers since 1973. The old site could not answer the two questions every visitor has: is it open right now, and what does it cost. The new one leads with exactly that, open status and today's hours computed from the schedule, then courses, prices, booking, news, the weekly programme, sponsors and a map. Every text, price and opening hour is editable by the board through an admin page. No developer needed when next season's prices change.

  • Open nowlive from the schedule
  • Self-serveboard edits everything
  • Thumb barprices, hours, book on mobile
  • Vue 3
  • TypeScript
  • Docker
asarumsbangolfklubb.se
Asarums Bangolfklubb start page: hero with open status card, courses, opening hours, prices
asarumsbangolfklubb.se/tavling
Tävling och spel page: three entry cards and the weekly programme list
Tävling och spel. The weekly programme as a list with weekday badges, and a "first time here?" box because most visitors are.
asarumsbangolfklubb.se/nyheter
Nyheter page: latest article featured, year filter chips, card grid
Nyheter. Weekly results and club news, filtered by year. The board writes posts themselves, one form, no markdown.
Start page on a phone with the open-now card and bottom action bar
Tävling page on a phone
Nyheter page on a phone
On a phone. A fixed bottom bar with Priser, Öppettider and Boka oss. Someone standing in the car park should need one tap.

Own tools

grindify.io
Grindify landing page: Train. Track. Own your data.

Grindify

v1.2.1 · Live · open source

Gym tracker built for my own training, self-hosted at app.grindify.io

A free web app for building your own gym programs and tracking workouts: weight, reps, sets, streaks, progress per lift. The functionality of the paid fitness apps without the subscription or the data lock-in. Installable PWA, works offline, and anyone can run it themselves with one Docker Compose command.

  • Own dataself-host or managed
  • PWAoffline, installable
  • AGPL-3.0source on GitHub
  • Vue 3
  • NestJS
  • PostgreSQL
  • Docker Compose

Project Hub

2025–2026 · In production · single user

One place for everything I run: uptime and response times per service, Docker containers, CI runs, issues, milestones, releases and an encrypted vault for env variables. Built because I got tired of checking six tabs to find out if Grindify or a client site was down. No design phase, I built it straight in code and fixed the UI as I used it.

  • 19containers monitored
  • 11projects, 4 linked repos
  • Encryptedenv vault, auto-lock
  • Vue 3
  • TypeScript
  • Spring Boot
  • Postgres
  • Docker API
  • GitHub API
Project Hub dashboard: 11 projects, 9 online, pinned project cards with status tags
Dashboard. Four numbers at the top answer the only question that matters at 7 am: is anything offline. Pinned projects below, each with status, environment and container count.
Project overview with uptime, response time chart over last 60 checks
Project overview. Uptime for 7 and 30 days, latest response time and the last 60 checks as a chart. Green online, red offline, nothing else.
Infrastructure view listing Docker containers with CPU and memory
Infrastructure. Every Docker container with image tag, CPU and memory. Restart, stop or open logs from the card.
CI / Actions list of GitHub workflow runs with status, branch and duration
CI / Actions. GitHub workflow runs synced per project. Status, commit, branch, duration, age.
Milestones synced from GitHub with progress bars
Milestones. Synced from GitHub. Progress bar, closed vs open, one click to the issue list.
Releases view rendering the changelog for v1.2.1
Releases. Changelogs rendered from GitHub releases or written locally. Read in the same place you check the deploy.
Environment variables vault with masked values and per environment filter
Env variables. Encrypted vault per project, filtered by environment. Values masked by default, auto-locks after 15 minutes, exports as .env or JSON.

VueKit

Paused · unreleased · Apache-2.0

Visual theme builder for Vuetify 3. Solo: design, frontend, backend, infra.

Setting up a Vuetify theme normally means hand-writing colour palettes and component defaults in a config file, restarting the dev server, and hoping. VueKit flips it. You build the theme in a panel with three modes, Presets for global settings, Theme for the light and dark palettes, Components for the props of 65 Vuetify components, while a live preview renders against Vuetify's real theme API. When it looks right you export a ready defineVuetify config in TypeScript or JavaScript and paste it in.

No account needed to use it. Sign in and you get saved themes with version history and rollback, reusable colour and component templates, and a public gallery where themes can be shared, cloned and liked.

  • 65configurable components
  • 3 + 5preview layouts, presets
  • TS / JSexport and import
  • Vue 3
  • Vuetify 3
  • TypeScript
  • Pinia
  • Node · Express
  • Prisma · PostgreSQL
  • Redis
  • Docker Compose
localhost:5173/builder
VueKit theme builder: components panel on the left, live component gallery on the right
Presets panel with five quick presets and global settings
Presets. Five starting points, then global settings that hit every component at once.
Theme panel with the dark palette: primary, secondary, success, warning, error, info, background, surface
Theme. Separate light and dark palettes plus your own colour variables. Every swatch updates the preview.
VueKit landing page with a mini theme builder demo
Landing page. A cut-down builder right on the start page, so you try it before you read about it.

Earlier work · BTH

SparkRentals banner: two riders on e-scooters, Software by Students

SparkRentals

2022 · team of 4 · MIT

A complete rental system for a fictional e-scooter company in three Swedish cities. Six repos in one Docker Compose: a REST API on MongoDB with Google OAuth, an admin dashboard with live map, a customer web client, a React Native app to rent and return, a simulator that moves hundreds of scooters along real routes and drains their batteries, and a data generator. The point was the system, not any one screen.

  • 6 reposone compose up
  • Simulatorscooters on real routes
  • 3 clientsadmin, web, mobile
  • Node · Express
  • MongoDB
  • React
  • React Native
  • Docker Compose
FalkenDev / LaTeX-Linter banner

LaTeX-Linter

2022 · solo · Python

A terminal tool that formats .tex files so a group can share and merge them without diff noise. Four rules: indentation inside environment blocks, one sentence per line for cleaner git diffs, a space after every comment %, and a fixed number of blank lines before section and chapter. Every rule is adjustable in settings.json or from the menu. Unit tested, packaged as a Docker image on Docker Hub.

docker run -it \
  -v $(pwd)/in:/latex-linter/input \
  -v $(pwd)/out:/latex-linter/output \
  falkendev/latex-linter:1.0
  • Python 3
  • unittest · pylint
  • Docker · Alpine

Research

Generative AI's impact on user interfaces in data-intensive web applications

Bachelor thesis, 15 hp · BTH, Software Engineering · 2024
With Joel Funk Persson · In collaboration with Connectitude AB
Supervisor Eriks Klotins · Examiner Jürgen Börstler

  • GPT-4fine-tuned, inside a real GUI
  • A/Bplus usability tests and interviews
  • 35 pagesEnglish, peer reviewed

The question: does putting a generative AI into a data-heavy web app actually make it easier to learn and understand? We built it to find out. A fine-tuned GPT-4 model next to a traditional interface in a data-intensive application, then A/B tests, usability tests and semi-structured interviews with and without the AI.

Result: mixed. People with the AI sometimes felt more efficient and more engaged, but slow and unreliable answers cancelled that out. The AI version did not beat the plain interface on the usability measures. The potential is there, but it lives or dies on accuracy and response time. Two years later that still holds, and it is the reason I care about latency in every UI I build.

How it works

Two things, done properly.

This is a side thing. I take on a few projects a year and pick the ones where a good site actually matters for the business.

  1. 01

    Websites for small businesses

    A clear, fast site that says what you do and makes it easy to get in touch. Designed with you, built to be updated without me.

  2. 02

    Maintenance & hosting

    Domain, hosting, backups, updates and the occasional text change. One person to call, and it keeps working.