Project Postmortem

Project Postmortem
Photo by Nikola Đuza / Unsplash

I keep falling into the same trap - get excited, start a project, work on it for a bit, get bored of it, think of another project, repeat. I'm not alone. But, I'm trying to be better. After all, I want to build the habit of completing projects.

Part of that is defining, before starting, when a project is done. It's too easy to let the project grow by saying yes to small bits of extra work! The reason its easy is that future work is like debt - take it out now and you don't have to pay it until you start work.

At some point, though, that debt load gets too high. The expectations, the daily investment needed, the lack of reward, it all comes crumbling down and the project becomes a chore, neglected, and eventually suppressed.

There's always some guilt involved though... why start a project that you weren't planning on finishing? And so instead of taking out debt for future projects, I'm trying to be better at paying off existing loans before taking on new ones.

This post is a tribute to the many projects that I've started but haven't quite let go of yet. Each of them showed some potential, but met an untimely end. With their passing, I'm freed to focus on the projects that I need to finish instead. This is me consolidating my debt and trying to re-finance.

Let's get started with the funeral procession and go over the projects.

Tick Task

The motivation of Tick Task was to create a cross-platform macOS and iOS app that let me set a timer on one device and have it go off on all devices. I wanted to keep it simple, stupid, to start.

The Tick Task logo

I spent a decent amount of time getting the "feel" of the timer just right. I wanted to dial to "click" into place, and sync across iOS and macOS. I spend a decent amount of time testing notifications to make sure that everything was working flawlessly. I had some hidden macOS functionality like holding option to "snap" into 5-minute increments, or shortcuts to load the previous setting. On iOS I added haptic feedback, as well as a mechanism for more granular control the further away the user's finger was from the center.

I also spent a good deal of time getting screenshots for the iOS and macOS app stores in the 11 different languages that I wanted to distribute in. I even wrote another program to help do just that.

Why did I make it? Apple didn't have a good solution for cross-platform timers. Why did I stop? Apple rejected the app because they said it didn't meet the "minimum functionality requirement". So lame.

Now, I just use Focus - which has a lot of features, sure, but the one I use the most? The cross-platform timer. Anyway, this one is sent to the graveyard at the hand of Apple.

Promptly

Promptly was my solution to Midjourney's awful implementation as being a Discord bot. What a terrible experience. If you wanted to re-run a prompt you'd have to manually edit the text and make sure that you had typed it right. It was like running console commands in a social media app. On iOS it was even worse.

So I created a cross-platform macOS and iOS app that allowed me to use a visual interface to edit the parameters. I was able to add multiple thoughts, reference images, with respective weights, as well as modifying the seed or keeping it consistent.

It made editing something like:

https://images.squarespace-cdn.com/content/v1/60ce8d5abb807927ef442293/e4b0398d-370b-430e-a7fa-720364a0815e/website_logo.png?format=1500w https://m.media-amazon.com/images/I/31+Csvr3xWL.jpg Fork on plate, logo, graphic illustration, design::1.0 low quality, pixellated::-1.0 --seed 3978030095 --iw 1.0

A decently short example prompt

Much easier because I could directly edit the parameters and then copy the prompt to use in Discord. Was the UI great? No, not really, but at least it was a leap up from the console-command line editing.

Now, Midjourney has opened the floodgates to their Web UI which is much better than Discord. Promptly is no longer needed, and it quietly retires to the app graveyard. The culprit? Midjourney actually developing a good user interface.

Aside: I did send a job application to Midjourney asking if they wanted any help developing a iOS and macOS application... crickets. At least they figured out they needed one eventually!

Yes it's not great, but I threw it together in a day.

joshgrant.github.io

I tried using Jekyll on GitHub, I really did. But after trying out Ghost I couldn't manage to care about Jekyll. I like... features?

So I've retired my Jekyll site and have migrated everything over. Good riddance!

Counting Stickers

I was inspired by Atomic Habits where James Clear discusses ways to reward yourself for habit forming. One such way was to have a "bean jar" where you could add beans for completing something unrewarding, like flossing.

I tried it - it didn't work. The problem? It's not intuitive to walk over to a jar of beans and put a bean in. Where are the beans that go in the jar? Do you have to remember the number of beans you've earned? Do you need bean jars scattered throughout the house to make sure you don't forget? What if you are hungry and want to eat the beans?

So I tried to make stickers - simple, just using emojis and colors - but when I saw that printing custom stickers was expensive, I needed to find another way.

So I got some index cards and found simple stickers (red, yellow, green, blue) and tried that for a while. The index cards were scattered throughout my house and had labels for what they were for (meditation, practice guitar). However, I wasn't sure if I was always going to use green? Or did the colors have meaning?

It was also not visually appealing to have index cards on tacky tape stuck to my walls with some stickers. I felt like I was in School of Rock.

So, I've decided to retire any concept of "bean counting" for the time being since at the end of the day what's much more powerful is building actual rewards into your daily routine, rather than relying on something that at the end of the day, isn't actually rewarding at all.

Now... maybe if there was a way to redeem points, it could be interesting.

Macros

This was a Swift Package that allowed me to do functional programming techniques in Swift by having some macros like easy struct initialization. For example, instead of writing:

struct Example {
  var name: String
  var location: String
  var age: Int
}

extension Example {
  init(
    example: Example, 
    name: String? = nil, 
    location: String? = nil, 
    age: int? = nil
  ) {
    self.name = name ?? example.name
    self.location = location ?? example.location
    self.age = age ?? example.age
  }
}

You could just write:

@EasyInit
struct Example {
  var name: String
  var location: String
  var age: Int 
}

It was great when paired with a functional reactive reducer, but at the end of the day, I've switched over to using Point Free's Swift Composable Architecture.

They use inout functions instead of a custom initializer, which works great.

This project is dead because a better framework took its place.

Protyper

Protyper was a fun project I used to quickly prototype UI designs on... the command line. Yes, you heard that right.

It mimicked the behavior of UIKit elements with similar logic, such as a first responder chain, table view delegates/data sources, and subview management.

For example, if I wanted to show a tab bar that contained a table view, it would look something like this:

Home                                    
––––––––––––––––––––––––––––––––––––––––
Tasks:
- Do laundry ✓ 
- Get groceries 

Notes > 

––––––––––––––––––––––––––––––––––––––––
          Home         Settings         
––––––––––––––––––––––––––––––––––––––––

An example of the command-line UI

Things like the padding of the tabs, navigation, and buttons, were all handled via the first responder chain (navigable by keyboard), and the window would redraw. The equivalent code was:

let home = ViewController(title: "Home")
let tableView = TableView()
tableView.dataSource = dataSource // I created this separately
home.view = tableView
let homeNav = NavigationController(root: home)
        
let settings = ViewController(title: "Settings")
let tabController = TabBarController(tabs: [homeNav, settings])
        
let mainWindow = Window()
mainWindow.rootViewController = tabController
        
mainWindow.draw()

I originally designed it with testability in mind (comparing text is easy!), as well as making the UI layer not so strongly tied to UIKit. After all, if I could write the code first in Protyper, then it would be more modular.

It was a fun project, but ultimately became superseded by SwiftUI, which is much better! Now I can rapidly prototype functionality and have it look good too.

tenhittender streaming

I started streaming for the lolz, mostly to capture the crazy moments with my brothers when we're playing games. I enjoy it - it's an easy enough hobby. I don't have many followers, just 9, and most of them are promoters asking if I want to buy bot views or have them advertise me on social media. It's kinda a joke. I don't honestly think I have the personality to stream solo, and I can't build a business around the availability of my brothers, who work different hours than me.

And in the end, what's the point? Do I really want to start a streaming empire? Follow a schedule, grind on games, invest in a studio? I'm mostly about just hopping on my Xbox occasionally to blow off some steam or explore a random world.

That said - the banter between me and my brothers is a lot of fun. So I still stream so I can capture those moments when they are being crazy and zany. Maybe eventually I'll upload clips on YouTube. But for now, it's a passive project that I'm not actively investing in.

Chatty

I worked on Chatty because I was trying to write a story, and I found it difficult to give characters their own unique voices. So, I created a chat app that let me "talk" to fictional characters and discover their personality. It worked well, and I wanted to redesign it with the Swift Composable Architecture, which I ended up abandoning because it didn't integrate well with SwiftData.

Maybe once I finish my SQLite wrapper, I'll bring this project back to life, but for now, it's finished!

0:00
/0:11

Nudge

An app I made for budgeting. It allowed me to categorize everything and set specific parameters around how money was flowing in and out of my accounts. It helped with budgeting and projecting my future net worth.

I liked it a lot! But now I use YNAB and find it a great tool that fits the bill. Nudge got me moving in the right direction, and YNAB has the staying power of a great budget tool.

Goodbye Nudge, it was nice knowing you!

Conclusion

These projects took time and rewarded me with some fun and useful additions to my life. I appreciate them for what they are, but wrote up this postmortem to say goodbye.

The projects are over, long live the projects!