Introducing RunewordsApp

A simple open source SwiftUI app for Diablo II

Thomas Ricouard
5 min readSep 6, 2022

My favorite video game franchise of all time is most probably Diablo, I’ve been playing it since forever, and the release of the remaster of Diablo II (Diablo II Resurrected) last year was the best thing to ever happen to the franchise. I’ve been playing Diablo II for the last 20 years, I can play it for 20 more.

Last weekend I had a bit of time to do two of my favorite things:

  • To play Diablo II Resurrected, I didn’t really played this season because I’ve played it way too much prior to the launch of the first season. But I’ll definitely play it for the season 2, whenever that may be… (But it should be soon)
  • Make a new SwiftUI project from scratch as I wanted to really explore the latest iOS 16 API.

What came out of it was a SwiftUI app for Diablo II. As usual the code is available on Github

In Diablo II, one of the most exciting part of it are runes and runewords, this is little stone you can collect and combine to make powerful items. While playing it I’m always struggling to remember the correct runes combinaisons for runewords and where to find them, etc... I need to google it, loose time to find the correct datasource, etc..

This is now over as I’ve made a little app to solve exactly that.

The app

You can see all the runewords available in the game, and easily filter and search them. This was really easy to achieve, thanks to the enhanced SwiftUI Searchable API, you can see the code below, it’s just a few lines to achieve all this behaviour. I love the new tokens API so much!

In the Runes tab, you can easily select runes and see what runewords can be made ouf of them. It’s a sort of reverse search and it’s very useful early game, when you start to have some runes and wonder what to craft.

And there is also a very detailed Rune screen where you can see how and where to find it, alongside the possible runewords from it.

This is about it for the functionalities, I’m still working on the stash feature where you can collect runes and the app will let you know which runewords you can craft.

SwiftUI really make all of that fast & easy, appart from finding and formatting the data, this has been the work of a few hours and I have a perfectly functional app that I plan to use a lot while I play the game. I might publish it on the App Store if I ever make or find a good icon for it.

Architecture

The architecture is really straightforward

The data live in its own Swift Package, RunesData. It’s where it’s all started, and it allowed me to run my tests before I even had any UI.

I can’t stress enough how good Swift Package are, you should abuse them, most of the time I’m running just the current package + tests I’m working on and then it’s just a matter of importing it and using it in your app.

The two other packages are DesignSystem and Stash. DesignSystem encapsulate all I need things I need for the UI, custom fonts, colors, etc... I always extend SwiftUI Color and Font so it really easy to use alongside other SwiftUI native modifiers.

And the other one will be for the user stash, it’ll be mostly about storing user data.

Everything else are views and live in the app directly. If I had bigger and wider features I might have compartmented it into features packages, but for such a small project / app it would have been overkill.

For the app itself, it’s a simple Tabview:

The new NavigationStack is really nice, and so much better than the now deprecated NavigationView. I have a centralised routeur, so I’ve created a modifier to attach the routeur on each of my root views.

And then you can use NavigationLink anywhere in the app, if the type it’s handled, you’ll get to your detail view!

It’s really a small app for my own usage, but feel free to look at the code and contributes if you’re a Diablo II player.

Thanks for reading 🚀

--

--

Thomas Ricouard

📱 🚀 🇫🇷 [Entrepreneur, iOS/Mac & Web dev] | Now @Medium, @Glose 📖| Past @google 🔍 | Co-founded few companies before, a movies 🎥 app and smart browser one.