racing · software · open-source

#My new App GalleryMagic is 20 years late to the market

Published on June 29, 2025 · 1617 words · about 8 min reading time

My new macOS app GalleryMagic is available on the App Store. Arguably, it is 20 years late to an already saturated market. I built it anyway.

Ever wanted to send a collection of photos to a friend or family member? Maybe you wanted to share some photos from your last vacation, or a birthday party, or just some random photos you took? There's already a plethora of ways to do this. Flickr, Google Photos, Apple Photos, Dropbox, you name it. But they all have one thing in common: You can't really influence the visual appearance of your gallery all that much. With GalleryMagic you can, based on a set of templates that come with the app (and both existing customization points as well as more to come). With some in-app purchases, you can also publicly host your galleries on the internet, so you can share them with anyone that has a webbrowser

This is what a demo gallery looks like:

GalleryMagic example gallery

Given my sister sometimes has the need for html galleries of her photos, I had dabbled in gallery generation before. Static site generators like Jekyll or Hugo can do this, but they are not for the faint of heart (read: your mom). I have probably four or five abandoned prototypes on my private git repos, all of varying technological background that I was interested in at the time. Ruby code packaged in a way so it can be embedded in a macOS app, a SwiftUI app that tries to embed one of the existing open-source html gallery generators, and so on. None of them ever made it to any real usable state let alone to the App Store.

Fueled by AI

Now what made me start to dabble in this again? The belief that I can build a simple app that does this in a weekend (care to take a guess if this estimation turned out to be the case?), given we now have AI assistants left right and center. I had so far been disappointed by the quality of results the AI assistants could produce. Claude code changed that one evening and I came away impressed. So off I went one evening, vibecoding my way through some rough ideas, and by the following evening I had a working prototype that could generate a simple html gallery from a set of photos. By that point, the app was all local, simple html produced on your machine, no network involved. Claude did help me patching together a SwiftUI interface with a Rust CLI to do the image manipulation. HTML generation is implemented in Swift as well. So far, this turned out to be a great combination. For me, because I like both Swift and Rust, and for the app, because the ecosystems both lend themselves well to the respective tasks.

Claude reporting on commits in the repo See Claude struggling to identify the work it did.

Now today, or 601 commits later, the vibecoding part has only been a small part of the development. Out of all commits, only 21 were made by claude. So arguably most of the praise I can give to claude code is that it got me started by making me believe I can ship this quickly. And so I did. I shipped an embarrasingly work in progress app to the macOS App Store on May 2nd 2025, got rejected by App Review twice and finally got approved on May 3rd. Since then I have shipped 10 updates to arrive at version 1.5 today, June 29th.

Development is 30% of the effort

As usual, the development of the app itself has been the easy part. The hard part, for me, is everything else that comes with shipping an app: Marketing content, the App Icon, App Store bureacracy, and most of all getting the app noticed by potential users. So in order to aid visibility, I'll crank out a couple more blog posts about the app. So far, I have already submitted the app to macupdate.com and built a website. I'll also do forum posts, post on slack channels, and try to look into Apple App Store Ads, which I have used in the past for iOS but so far can't grok how to use it for the macOS App Store. My original plan was to, as quickly as possible, get a feel for the potential of the app. Only if there are early signs of there being a market for it, had I planned to invest more time into the app. Given that I enjoy working on it, I haven't been that true to this plan. It's really hard judging an MVP of a product and be willing to ship something you're not proud of or even embarrassed by.

What next?

I'll end this here with the output of cloc as of today. This includes the app itself, the website, the infrastructure code for the hosting as well as the image manipulation CLI. It always surprises me how little code it really takes to build something like this.

----------------------------------------------------------------
Language      files          blank        comment           code
----------------------------------------------------------------
Swift            49            358             85           3552
HTML             12            183             30           1574
Rust              2            105             40            613
Python            7             99             45            553
XML               7              0              0            248
Markdown          4             53              0            183
JSON              7              0              0            182
SVG               6              0              5             60
CSS               1              7              0             50
TOML              3              9              0             49
YAML              3              0              0             32
make              1              2              0              5
----------------------------------------------------------------
SUM:            102            816            205           7101
----------------------------------------------------------------

#Sometimes stuff just works

Published on August 08, 2021 · 376 words · about 1 min reading time

Software development is full of trip-wires, broken processes, short-living projects and more which often times make a developer's life difficult. Most software being broken all of the time is a very common sentiment in the industry. Developer tooling is also very easily neglegted. Believe it or not, against all expectations, a short while ago I had a pleasant experience:

My iOS App PitBuddy is still on the AppStore, but I had last shipped an update more than two years ago. I don't actively develop it anymore; let's say it is in maintenance mode. However, in iOS 13 I believe, some change in the default iOS styling led to a placeholder text in one of the apps TextViews be difficult to read. Should be easy enough to fix, I thought. Thing is, I hadn't even checked out the repo on my current machine let alone built the Xcode project. The project is a mix of Objective-C, some Swift, Cocoapods for any app dependencies. Now that's where most would assume I would have run into a world of hurt. However, I didn't:

bundle install --path=vendor/bundle

just worked. After that

bundle exec pod install

just worked as well. That's where I started to feel like I'm in a dream. Opening the project via

xed PitbuddyApp.xcworkspace

and building it via Cmd+B ran into a couple of minor warnings, but it completed just fine and I was able to run it in the simulator. By that point there was only one thing left to do: run tests. PitBuddyApp has a number of unit tests which built and passed, so that box was checked. I also have a couple of "Acceptance Tests" in place, using the KIF ui testing framework. So those didnt 't pass. However, I simply bumped KIF to the lastest version, and alas, I was back in the green. All in all, from cloning the repo to a fully passing build and test suite it took me no more than 30 minutes. So what do we take away from this?

  • Sometimes things just work
  • Dependency pinning (both the Gems as well as the Cocoapods) is good
  • The bump from Xcode 10 to 12 needed a bump of KIF

Thanks to everyone helping maintain bundler, cocoapoda, etc!

#The Swift Composable Architecture - A Review

Published on May 15, 2021 · 2945 words · about 14 min reading time

I have dabbled in iOS development, on and off, for many years now. Starting back when UIKit and Objective-C were still the only platform choices, continuing with exploring RubyMotion, slowly making the transition to Swift, playing with React Native and then seeing SwiftUI come to life ... it's been an interesting journey. For a variety of reasons, none of the opinionated options in building an app ever really caught my fancy. Sure, Apple leaves a lot of questions unanswered for architecting an iOS app, but generic patterns like MVVM or MVC can be applied to iOS development without selling your soul to any large third party framework. The smaller the app is, the easier it also is to kind of get away with not really following a specific pattern.

Past fall I set out to explore SwiftUI, and there's no better way to explore a technology than to build something with it. So I chose to develop an iOS game based on the mechanics of one of my older memories of SUSE Linux: KDE Konquest. A new Xcode project was initialized and off I went. At this point I have to give a shout-out to John Sundell, whose website Swift by Sundell was an essential resource for finding quick and easy examples and explanations about SwiftUI features. As the app grew in size (user facing) and lines of code, I became more and more dissatisfied with the way things were shaping up. Clean, modular code and high test coverage are aspects of my work I value a lot. However, in growing the code base more and more, these aspects kind of fell by the wayside. Now granted, I fully accepted that and made a bit of an experiment out of the project to not care as much as I usually do. Still, deep down inside me I knew: if I ever wanted to release and maintain the game, I needed to find a sustainable way to add features and regression test the application. To make matters worse, the game is supposed to be played via Apple's Game-Center, which makes it notoriously annoying to play-test against yourself. I only own a single iOS device, so testing with my device and a simulator is the only choice I have. And believe me, Game-Center and the Xcode iOS simulators are not best friends!

Meet the Swift Composable Architecture

I had come across Pointfree a decent while ago and have been watching the videos Brandon and Stephen put out. They are excellent, you should subscribe! Amongst other topics, they introduced this iOS architecture they call The Composable Architecture. Now probably this immediately resonated with me because I am in a phase of preferring a functional, compositional style of programming by now, more so than wild mutations all over the place and OOP for the sake of it. Dabbling in React in the past probably also helped me in grasping the concept of unidirectional data-flow. In any case, after being annoyed by some horrible SwiftUI views I had produced, mixing state management, side effects, presentation logic and visual styling, I took the plunge and decided to adopt the composable architecture.

#2021 Supercross Predictions

Published on December 28, 2020 · 790 words · about 3 min reading time

With 2020 coming to a close, the 2021 Monster Energy AMA Supercross season is right around the corner. The first round is scheduled to be held in Houston, Texas on January 16th. This gives us a couple of days to think about who will be coming out on top in both the 450, 250 East and 250 West classes. Actually, the 250 entry lists aren't public yet, so we can only try to predict the 250 field as a whole, not knowing who will line up on either the west or east rounds' gates. That sounds a bit too artificial, so let's focus on the 450 division.

#Measuring code coverage in crystal with kcov

Published on February 24, 2019 · 615 words · about 3 min reading time

Crystal, the programming language, does not yet provide a built in way of measuring the effectiveness of your test suite. So by running crystal spec you pretty much only have binary insight into the suite: it's passing or it's not. This lead me to build crytic in the first place. But while mutation coverage is a great tool to investigate the test suite, plain old code coverage is usually quicker to obtain and easier to glance at.