Building Apps That Don't Make Any Money
Tags: swiftui, startup, laravel, devjournal
Published: 2024-07-11 00:07:37


I've forgotten when it was released, but at some point in the past, I released an app called [Bill Panda](https://sunnyorlando.dev/billpanda), which you can read about following the link. It was my first complete app that I built to solve a personal problem. I went through the full experience of building it, tearing it down, rebuilding it, tearing it down again, and building it again. I created an LLC that the app is published under, a business banking account, and a light website to market the app. This is a post reflecting on some things I learned during this experience.

## Why I built it in the first place
For a long time I was using a spreadsheet to manage my recurring bills. There were apps out there, like Mint, that automate some of this stuff for you. But I always disliked that I couldn't mark my bills as paid ahead of time. I also couldn't use the data to create any cash projections. So i thought, why not build my own? It needed to do a few simple things:

1. Track my recurring bills.
2. Notify me of upcoming bills.
3. Allow me to mark them as paid/unpaid.
4. Let me add notes
5. And eventually, reporting, so I can make cash projections.

I originally built it using Laravel - a web application framework. The frontend was all in Vue and the backend was PHP. You can see a demo of it here (I demoed it for a Hackathon, which I won second place :D): [Bill Panda Web](https://devpost.com/software/family-newsletter.). The second time I used React Native. The third and final time, it was all Swift UI. It's been a fun journey building the app. I'm finally at a point where I can begin thinking about new features for it. But before I get to those, I thought I'd share a few mistakes I made along the way. You may find this helpful if:

1. You are about to build a payment system with recurrence.
2. You work with recurring events in general.
3. You plan on building your own app.

## Mistakes 

### 1. Regarding Recurring Events - Don't store every occurrence in your database!

When I built the web-based version, i made a critical mistake. For my use-case, you should never populate your database with all occurrences of a recurring event. Not only are you creating a TON of data, you also corner yourself by having to answer questions like "this event repeats daily until the end of time, do i create every single event until the end of time in my database? Do i cap it to the first 1,000 events?” Whats the right number of recurring events to create? There is no right number. 

During my research developing recurring events, I ran into this amazing post on Github by user bmoeskau: https://github.com/bmoeskau/Extensible/blob/master/recurrence-overview.md. This post sent me in the right direction. You do not create every occurrence, you compute them. You follow a recurrence rule standard that's been around since [1998](https://en.wikipedia.org/wiki/ICalendar). I highly suggest reading the github post I linked above if you are going to create a recurring event system!

### 2. Your friends and family may not like to use your app if they know that you have access to their finances

If you've built the application, you have access to the database. You can promise you'll never look at the database, but cmon, you probably will. Trust is a big thing when it comes to finances - your friends and family probably won't want to use your app if it means handing over all their data. You have to **guarantee** that their data will not be accessible to you. During the time that I developed the web app, I did not have a way around this. But by pivoting the technology I used, I did find a way. 

At some point in the last couple of years, Apple announced SwiftUI. 
This looked so interesting that I ended up diving back into iOS development (I've jumped back and forth between iOS/Android app development and Web Development in my history). As I started working in SwiftUI, I thought, why not try CoreData one more time? Maybe work with CoreData and CloudKit. If i was to incorporate CloudKit, the user never has to sign into the app. All their data can live inside a private CloudKit container that I, as the developer, have ZERO access to. It also has an incredible generous free tier that makes it so that I don't have to pay anything. Furthermore, CloudKit data syncs across your iOS devices seamlessly. It had everything I needed (it was also a huge, painful, learning curve). Happy to say that I made the right decision :). The app is running fully on CloudKit.

### 3. Not working with technology you love
If you have a hobby project and your goal isn't really to get rich, then don't work with technology you loath. This is not to say that I hate Laravel or Vue (they powered the first iteration) - I truly love those technologies. No, the one i tend to loath sometimes is React Native -- which I used for the second iteration of the app. 

If you look at a prior post of mine (https://dev.to/m4rcoperuano/react-native-best-practices-when-using-flatlist-or-sectionlist-4j41), I wrote:

> ...React Native has been the only [language]that has been able to change my mind and has me questioning why I would ever want to code in Swift or Java again.

Looking back, this is still true.....sometimes. Sometimes I hate it. The debugging (not knowing if the bug is in your javascript code, your native module, the react native run time, or once its packaged) is maddening. This doesn't mean I would never code with React Native. For example, if you want to make a cross-platform app, or if it's a requirement from your client/job, then its no problem. But if you're doing it for fun, and you don't care about cross-platform, then save yourself the headache. Work with the native code and framework.

But I digress. If you are working on a hobby project, work with tech that you love. It will motivate you to keep going back to it. Personally, I love using SwiftUI and sometimes wish it was all I did. 

## Sidequest: Why Is SwiftUI Awesome?

SwiftUI is pretty darn cool once you get the hang of it. This is a framework that Apple has developed so that its easier to make native iOS apps. Here's a quick example:

```swift
struct MonthHeader: View {
   var monthName: String;
   var totalDue: Int;
   var amountPaid: Int;
   
   var body: some View {
      VStack(alignment:.leading, spacing: 2) {
         Text(monthName)
            .font(.headline)
            .foregroundColor(Color.textGeneral)
         
         HStack {
            Text("\(amountPaid.toCurrency) paid ")
               .foregroundColor(Color.brand)
               .font(.subheadline.bold())
            +
            Text("out of \(totalDue.toCurrency)")
            Spacer()
         }
      }
      .padding()
      .background(.thinMaterial)
      .listRowInsets(EdgeInsets(
         top: 0,
         leading: 0,
         bottom: 0,
         trailing: 0))
   }
}
```

This is a pretty simple view that displays this:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s37vf6c98m4jd1lw9zyn.png)

I find this code super readable. You have:
- 3 required parameters defined at the very top. These are your "props", essentially (if you are familiar with Vue or React)
```swift
struct MonthHeader: View {
   var monthName: String;
   var totalDue: Int;
   var amountPaid: Int;
....
```
- You then have you "body" field, which is essentially a `template` tag, or what you return from a React component (again, if you are familiar with web). You can learn what the code does by reading my comments below:
```swift
   var body: some View {
      //VStack stands for Vertical Stack
      VStack(alignment:.leading, spacing: 2) {
         //Inside it we have a Text field that displays your prop,
         // monthName. It's then modified to look like a headline 
         // with a specific foregroundColor.
         Text(monthName)
            .font(.headline)
            .foregroundColor(Color.textGeneral)

         //Then you have an HStack, or Horizontal Stack, that takes
         // your prop amountPaid and uses an extension (a function) 
         // that converts it to currency. It also sets the color to a
         // specific "brand" color that I selected, and makes the 
         // font a subheadline that is bolded. 

         //Finally, another text element is right next to it 
         // (concatenated) that represents the amount due. The reason 
         // is separated from the first Text element is because I 
         // don't want it to be colored at all.
         HStack {
            Text("\(amountPaid.toCurrency) paid ")
               .foregroundColor(Color.brand)
               .font(.subheadline.bold())
            +
            Text("out of \(totalDue.toCurrency)")
            Spacer()
         }
      }
      //Then i apply some padding, change its background color to a 
      // .thinMaterial, which apple has provided -- it changes the 
      // background color to be blurred and translucent
      .padding()
      .background(.thinMaterial) 
      //finally, i remove any default padding provided by default 
      // from Apple's SwiftUI framework
      .listRowInsets(EdgeInsets(
         top: 0,
         leading: 0,
         bottom: 0,
         trailing: 0))
   }
```

Compared to the past, where you would have to create Swift ViewControllers, or worse, Objective-C ViewControllers, this is much welcome change. If my job was to create Swift apps full time, man, that would be exciting. 

## Summary

It took about 3 years to get the app to a state where I was happy with it. The app was built during nights and weekends, sometimes on vacations. It, thankfully, wasn't too stressful to build. If you love to code and you have a goal in mind, then you'll find the time to make the app that you always wanted to make. Its okay if it takes a long time--we have day jobs. Will I ever make money on this app? I don't really know and I don't really think about it. It serves its purpose to me and a few others (I have about 40+ daily users!). That's all I need to be content with it :).