Introduction

This is a book about how I created Bank Statement Converter. It's also available on Amazon and Gumroad if you'd like to read it there instead.




March 2021, Initial Commit

I had my job four months ago. I had spent my time hiking around Hong Kong and coding a web version of a mobile app I had created called  Girlfriend Plus. It wasn’t going great, the backend I created was way too complicated and I wasn’t really sure how to get people to use it. Another problem, the web version was a lot worse than the mobile version.

The mobile version sends you notifications and it runs 100% offline. The mobile version also had a better user interface. In the last four months Girlfriend Plus Web brought in about $6.

Month

Revenue (USD)

December 2020

$2.99

January 2021

$2.99

February 2021

$0

March 2021

$0

I was not succeeding as an entrepreneur.

One day I realised I had saved up a lot of money, but I didn’t really know how much I was spending. When I was working I got paid a lot, and my bank balance would go up every month. After leaving my job, my bank balance started going down every month. Bad. I decided I wanted to download a CSV file with all my bank transactions in it, so that I could figure out how much I was spending a month. Then I could figure out how many months I could survive without making any money. In the business world this is called your runway.

If you’ve got $100,000 in the bank, and you spend $10,000 a month, you have ten months of runway.

I spent some time on HSBC’s internet banking site and realised all they could give me were PDF bank statements. I tried to copy and paste the data into a Google Sheets document but it didn’t work. I then thought “Angus you are a computer programmer, program the computer to do this for you”

That was a good idea. I created a new Kotlin project in IntelliJ, the first class I wrote was called HorseTest.kt. This is because I am a good boy and I take part in a development process known as Test Driven Development. Some people are not a fan of this process.

The name of the test says “should be able to say good morning”, but the code said “Hi Angus”. It was all okay though, I wasn’t there to build an app that greeted me, I was there to build a Bank Statement Converter. I quickly discovered Apache PDFBox and it seemed to be a good thing to use for reading PDF files.

PDFBox contained a class called PDFTextStripper, it sounded pretty sexy so I tried it out. It was able to get text out of the PDF, which was pretty cool.

In the image above I have replaced my bank balance with “XXX”. My bank balance is very large and I do not want to shame the reader.

It came out quite nicely, but I wanted it to come out even nicelier. I wanted the niceness to be nice in a way that looked like this:

Pretty nice eh. However, sadly, it isn’t possible to get the text above into that shape.

This is because the x position of the text “3.84” tells you that it belongs to the “Deposit” column. I needed a rectangle with every piece of text. I could associate a piece of text with a column by seeing which heading it intersects with. The text “298.00” intersects with the column named “Withdrawal”, therefore “298.00” is a Withdrawal.

I poked around through the code of PDFBox and found a class called TextPosition.java it has properties for text, x, y, endX and endY. Basically it stores text and a rectangle telling you where on the page that text appears. Perfect.

I continued hacking on this for a few more days and came up with a cool algorithm that went something like this:

  1. Read a page of the PDF
  2. Get all the words out of that page
  3. Group the words into lines
  4. Look for a line with the text “Date Transaction Details Deposit Withdrawal Balance”. This is the header of the table.
  5. Find the bottom of the table using the gaps between lines. Once there’s a big enough gap, the table must be done.
  6. Get the words between the header and the bottom.
  7. Associate those words with a column based on whether they intersect or not.

Note: In this world a word is not really a word. “CSL MOBILE LTD” is considered a word in Bank Statement Converter speak. Sometimes in programming we like to use words incorrectly. We do this because we are annoying.

This algorithm worked pretty well and I was feeling pumped. I started thinking “Wait a minute, HSBC is the biggest bank in Hong Kong, if I need this tool, then surely there must be other HSBC customers who need this too? I should make this into a web application.”

At the last company I worked at I became friends with a really good front end developer who went by the name Dominic. The two of us would always talk about building apps. I would say “We should make an app”. Then Dom would say “Yeah man we should make an app”. Then we would sit in silence as we realised we had no idea what app to make.

Would Dom be interested in building the UI for this bank statement converting web app?

I’m a cool guy so I started the conversation off by telling Dom he didn’t need to worry about whatever nonsense was worrying him. In business this is called “Disregarding other people’s feelings”.

April 2021, Enter Dominic

Saturday April 3rd 2021.

I spent the day at my Dad’s house, then later I went over to meet Dom at Lan Kwai Fong. We met at a Japanese ramen place called Nojo.

Dom gets something to eat but I think I already had dinner so I just drank a beer.


Angus: Okay here’s the idea. A website where you upload a PDF bank statement and then it gives you back a CSV file.

Dom: Who needs that?

Angus: Accountants I guess.

Dom: How does it make money?

Angus: We let people convert some documents a day for free, and if they need to do more, we sell them credits.

Dom: What’s the front end going to look like?

Angus: It’s one page. People upload a PDF to the page, and then we trigger a CSV download.

Dom: I do the front end and you do the backend?

Angus: Yup.

We talked a bit more, but basically Dom liked the idea. I told him I didn’t really know if it was going to make money or not, but it’s a pretty simple app and we could use it to figure out if we liked working together. While at Nojo we decided on the domain name bankstatementconverter.com and Dom bought it.

It was an Easter long weekend so Dom had the next two days off work. I was paying for a hot desk at a coworking space in Sheung Wan but I bought the cheap plan so I could only go in on business days. Dom was living at Jen Hotel in Sai Ying Pun and they had a business centre. We agreed to meet up there the following day to work together on Bank Statement Converter.

Sunday April 4 2021

The next day we met up at 12:00 PM at JEN Hotel. At this point the core converting part of the application could only be run through test cases. I needed to set up a web server, and get the conversion functionality happening behind an API. Probably something like:

POST /api/v1/BankStatement

Where the body of the POST statement is a PDF file and the response is a CSV file. Sounds pretty cool to me, a REST API with a single end point.

There were other things that needed to be done:

  1. Build the front end. Dom’s job.
  2. Connect the front end to the back end. Dom’s job.
  3. Get some virtual machines on AWS. This is where the backend will run.
  4. Write Ansible scripts to test and build a JAR.
  5. Write Ansible scripts to deploy the JAR to DEV and PROD.
  6. Put the front end on the domain.
  7. Put the back end on the domain.
  8. Get SSL certificates. Argh this is always fiddly.

These are all things I have been doing since 2016. They’re time consuming tasks, but not difficult. I just sat down and got to work copying bits and pieces from other projects I had on my computer.

As Dom worked on the front end he noticed my single API solution had a problem. The file uploading widget he wanted to use didn’t really expect a file download response. It also wanted to send one request per file.

Dom: With the one API approach, what if I’m uploading 100 files, and I lose internet on file #99. I’ll have to upload all 100 files again.

Dom had a good point. Nice thinking Dom. We decided to break it up into two APIs.

File Upload

POST /api/v1/BankStatement

The request body is a PDF file. The response body is a universally unique identifier (UUID).

PDF Conversion

POST /api/v1/BankStatement/convert?format=CSV

The request body is an JSON array of UUIDs that represent an already uploaded PDF. The response body CSV of the transaction data in that bank statement.

This worked pretty well, and I believe on that day Dom was able to call the two APIs together and trigger a file download.

Reading this you’re probably thinking. “Wow! These two cool guys were able to get the app running in one day”. In reality what we built could not really be called a Bank Statement Converter. It only worked for HSBC bank statements. A better name might be “HSBC Bank Statement Converter”.

Lots of other important features were missing. Features like:

  1. Payment processing
  2. User accounts
  3. User credits
  4. A real database. The first version wrote to a mocked out database that wrote state to in memory data structures. This meant all state was wiped when restarting the backend process.

                

Launch Day - Friday April 9 2021

Dom and I worked at my coworking space in Sheung Wan. Dom gets it running live on bankstatementconverter.com

Here’s what it looked like when we launched. One thing you’ll notice is as soon as we launched we were the world’s most trusted and accurate bank statement converter. I’m not sure how Dom knew this was the case, but I’m glad he was able to figure that out and tell our users about it.

Here’s what it looks like today (February 2024). Not massively different is it? One thing that changed is we replaced “Approachable” with “Accurate”. As time has passed us by, the Bank Statement Converter has gotten more and more accurate, while the company has gotten less approachable. I get a lot of emails every day and I ignore the majority of them. This is not good, people like it when their emails are replied to.

What next? Sit back and watch as the money comes rolling in? Well that would have been a swell idea, but sadly the app didn’t really work properly. Which meant if someone stumbled upon the site and uploaded a bank statement, the resulting CSV would be pretty bad. They would then leave our site and never return.

I knew I had to do the following things:

  1. Make the algorithm better
  2. Get people to use the app
  3. Get some money from the users

Being a smart boy with a speedy brain I was able to come up with a smart and speedy plan to do these things.

Make the algorithm better

I thought “I need to get a lot of bank statements, from a lot of different banks, then I can come up with a cool algorithm that works for all these banks”. Then I thought “How am I going to get a lot of bank statements?”

Wait a tick. What if I didn’t do it, but instead I hired someone on the internet to get these bank statements for me? I went onto upwork.com and placed the following job ad.

At the time the app was known as “Festive Ritchie”. Festive Ritchie is a good name for someone who wears Christmas sweaters. It is not a good name for a bank statement converting app. Don’t worry we changed the name. If we didn’t change the name this book would be called “Festive Ritchie - Zero to $200K a Year”.

Get people to use the app

This should be easy right? All I needed to do was to enlist the help of Mark Zuckerberg. Mark’s a cool guy. Mark allows you to place ads on his website (facebook.com) in exchange for a fee. I filled in one of his forms to place an ad and then hit submit.

“You have been banned”

Oh no. I guess Mark wasn’t feeling so cool today. I had done something to anger him. Darn. I poked around for a little bit but could not figure out how to get myself unbanned. I suspected the ad I placed made my website look like a scam. “Bank Statement Converter” sounds like a scam to steal people’s private banking information.

I came up with a new plan. To enlist the help of the Google brothers, Leeroy and Cedric Brin. You see, the Brin brothers allow you to place an on google.com in exchange for a fee.

“Dom, let’s place ads on Google instead”

Ads on google.com don’t contain any pictures. They are all text based. That should make buying an ad on google.com simple. However, buying an ad on Google was very complicated. Luckily I am a perspirant person, and I was able to get through the long and complicated google form. As I filled in the form I would heat up, then I would perspire and cool myself down, then I would continue to fill in the form.

On April 17th 2021 our first Google ad went live. Soon after that we started getting random people from the internet using our website.

Get some money from the users

This would require a little bit of coding. Setting up a Stripe account. Using a real database instead of a mocked out ephemeral one. Creating the concept of credits. Using up credits when users converted a document.

The rest of the month I basically spent improving the core algorithm and implementing the stuff needed to process payments. Getting money was very important to me. It still is.

End of Month Numbers

Users

3

Revenue

$0 HKD

Ad Spend

$1110 HKD

May 2021, First Paying Customer

It took me until May 7th 2021 to get the app ready to start processing payments. I met up with a friend called Koushal for lunch. At lunch I told him “The app is ready to start making money, how much do you think it’ll make in the first seven days?”

Koushal, I can read your mind.

I can’t remember what he said, but I could tell he was thinking “It ain’t going to make any money Angus”. Sometimes I can read people’s minds, especially when the mind is owned by a person like Koushal. Koushal is a simple man, he likes going to the gym and he likes reading about exotic fish.

For the next few days I improved the algorithm, fixed bugs and tried to hire someone to help me with marketing tasks. I spent a ton of time checking dashboards to see if anyone was buying the app. Every day I would wake up and see that no one had bought the app.

Once again, I was not succeeding as an entrepreneur.

Back in January 2014, I created an app called Girlfriend Plus. Within hours of releasing a build that allowed users to pay for content, someone did. I was expecting the same thing to happen with Bank Statement Converter, but it did not.

First Customer

Thursday May 13 2021

I woke up, and saw no one had bought the app. There was a lot of work to do, but I wasn’t in the mood to do it. I decided to go to Sai Kung and walk Maclehose Stage 3 backwards. My starting point is a place called Shui Long Wo. Soon after getting there I received an email.

At first I didn’t know what this guy was talking about. Then I realised he has paid for credits, and is running into some sort of an error.

Damn. If I were at home I would be able to deal with this. I messaged Dom and tried to debug the problem with him. We can’t figure it out. After a while I decide to just look at it when I get home.

I met a cow on the way. Pretty exciting.

The hike went pretty well. I got home very tired and somehow figured out how to fix the issue Rick had.

Generic Algorithm?

Sometime in this month Dom implemented a pretty cool feature. When a document fails to convert properly, he lets the users click a button to send us an email telling us about it. We get a lot of these emails. I look through the PDFs. I can’t figure out an algorithm that works for all these different formats.

The people at YCombinator like to say “Do things that don’t scale”. They have their reasons for saying this and it makes sense to me.

Along that line of thinking, I started thinking about creating specific parsers for specific banks and then providing users with links to convert their documents using a specific parser. The flow might go something like this.

  1. User uploads a Bank of China statement.
  2. It does not convert properly.
  3. User reports the error. Dom and I get an email.
  4. We write a BankOfChinaParser and redeploy the application.
  5. We reply to the user’s email with a magic link that specifies to convert a document using the BankOfChinaParser.

I never actually implemented something like this, because I came up with a much better idea a little bit later.

Dom Leaves

At this point Dom has resigned from the crypto exchange, but he has a few months left to work there. He doesn’t seem very interested in working on Bank Statement Converter. So I send him this email:

Dom replies that he’d like to drop out, but says he doesn’t need to be bought out. That’s very nice of him, and I make a mental note that I owe Dom for the work he did on Bank Statement Converter.

In a way this makes my life a little bit easier, I don’t have to discuss what to work on with anyone. However it does make me think “If Dom doesn’t want to work on this, does that mean it sucks?”

End of Month Numbers

Users

78

Revenue

$791 HKD

Ad Spend

$5700 HKD

June 2021, A Very Cool Idea

This is around the time I came up with a very cool idea. Actually the idea was implemented in May 2021, but that month had a lot of stuff going on, so I’ve rolled the “very cool idea” into this month instead.

At the time I had a problem. It was coming to the conclusion that a generic bank statement converting algorithm did not exist. I could create converters for different banks though. So what? Make the user tell you what bank they use and then run a parser for that bank?

Hell no. A bank like HSBC operates around the world. They probably have multiple formats for all the countries they operate in.

Also, if you give a user an input field, they’re going to mess it up. Users are very good at messing stuff up. It’s much better if the app can just figure out which parser to use based on the PDF itself.

I came up with this strategy:

  1. Use pieces of text or images in the document to identify the document type.
  2. Run a specific converter for that document type.

Example 1

  1. Oh look. This PDF has an HSBC logo on it. It has a width of 400 pixels and a height of 200 pixels. This must be the PDF that goes by the name of HSBC_HK_1.
  2. Hello HSBC_HK_1, good to see you again. I will convert you using the HSBCHKParser1 converter.

Example 2

  1. Ah, a new PDF has come to me. I don’t recognise this fellow. Well I’ll give him the name UNKNOWN.
  2. Since we don’t know who you are. I will convert you using the GenericTransctionParser converter.

The idea here is simple. Do a lot of work identifying PDFs. Write a lot of code to work for specific document types.

End of Month Numbers

Users

151

Revenue

$1246 HKD

Ad Spend

$8150 HKD

July 2021, Enter Subscriptions

Bleeding Money

At this point you may have noticed that I spent $14860 HKD on Google Ads and brought in $2037 HKD in revenue. For the third time in this book, I was not succeeding as an entrepreneur.

This was the first time I had used Google Ads so I naively thought “It’s just a simple matter of getting the ads to convert 7x better. Once I can do that, all will be good”.

Experienced users of Google Ads will say “You aren’t going to get a 7x improvement. You are borked”. Google Ads has so many settings to set. It seems like it should be possible. I feel like the mega brains at Google intentionally put in all those settings so that it seems like the ads can be tweaked to run more efficiently.

Non Bank Statements

For some reason, people would go to a website called Bank Statement Converter and then upload a PDF that was not a bank statement. Then they would email me and say “Yo this didn’t work. What the hell man!”.

Some would be tempted to reply saying “Hey man, look at the name of the website”. But I’m a cool dude and I think differently. If they sent an email, they probably care a lot about getting their data out of the PDF.

I came up with the idea to create a UI that would allow users to specify regions on their PDF. Then my app would use the spacing around the text to try to put it into a table.

It’s not a perfect solution. This UI appears when the user clicks the Preview button or when we can’t find any transaction data in a PDF. I’m not great at making user interfaces, I can do the logic part of a user interface, but I really struggle with the HTML and CSS part.

So instead of coding the UI myself, I posted a job on upwork.com

I hired some guys in Vietnam to do this. They did a good job, their code was a bit gross but it worked. Nice work guys. Shout out to David T.

Google Login

I implemented a Google login/registration flow. I think I did this because I couldn’t think of anything better to do. Now I know that when you can’t think of what to code, you should email your users and ask them what they need. It’s better than just imagining what they need.

I did notice something interesting after implementing the Google registration flow.

  1. 50% of users who registered with an email and a password would upload a PDF.
  2. 90% of users who registered with Google would upload a PDF.

Said more simply, the Google registration flow had a lot less drop off. This drop off term has to do with the Money to Angus Funnel.

Money to Angus Funnel

  1. A person uses the app for free without logging in.
  2. They run out of free credits.
  3. They register for some more free credits.
  4. They use the app for free some more.
  5. They run out of credits again.
  6. They buy more credits.
  7. Angus gets money.

At any of the steps a user can stop using the app. This is because I cannot put a gun to the head of people and force them to use my app. If a user drops off at any stage before Step #7, I do not get any money. That is bad.

Soon after that I removed the email/password registration method. I forced everyone to sign up with Google to reduce the drop off rate and make more money.

Every now and then someone tells me they don’t have a Google login or they want to sign up with their email. When that happens I pass them a special link.

Did this move reduce drop off and lead to more revenue? I’m not sure, at the time I was convinced it did, but I haven’t done the proper analysis to determine that.

Subscriptions

Up until this I was selling one off credit packages for Bank Statement Converter. Are you really running a software as a service business if you don’t sell subscriptions?

I wanted to try out selling subscriptions for unlimited credits instead. Instead of $X for Y amount of page credits the plan would be $20 every three months for unlimited page credits.

Which works out to about $6.66 a month. Pretty cheap. People seemed okay with this plan and I got 12 subscribers that month.

End of Month Numbers

Users

145

Revenue

$2397 HKD

Monthly Recurring Revenue

$569 HKD

Ad Spend

$10800 HKD

August 2021, Blogging Starts

Reducing Limits

At this point in time I was very generous with the free tier of the product. Anonymous (not logged in) users could convert 10 pages for free every 24 hours. Logged in users could convert 20 pages for free every 24 hours.

This meant users could log in, convert 20 pages and then log out and convert another 10. If they had 90 pages to convert they could get through them in 72 hours.

As a mean guy, with an eye on the dollar bills, I decided to cut the free tier limit. I cut it down to:

Why so mean? Users were creating multiple accounts, so I wanted to make it more annoying for them to do so.

Error Reporting API

When something goes wrong in the backend, I write a record into the database. I check these errors to make sure the app is working properly. However I wasn’t doing this in the front end. So I created an API for the front end to send error reports to the backend.

Jacalyn Emails Me

One day I got an email from a user called Jacalyn. She wanted to know why something didn’t work. I have a look and see that she uploaded an image based PDF. This means the PDF has no text elements in it. It’s either a scanned bank statement, or some sort of annoying bank statement where they render out pixels instead of text elements.

I don’t really know why, but some banks like to protect their PDFs so that computer programs cannot extract the data. I call these banks scumbag banks.

Other banks like to put in little clues to help you extract the data from the PDFs. I call these banks nice guy banks.

Since Jacalyn’s document was a scanned PDF. I replied to her saying “I’m sorry we don’t handle scanned PDFs”. Then I stood up from my desk, put on some shorts, opened the door, got in the lift, pressed “G”, walked out the front of my building and started running from my house in Tin Hau to the Star Ferry Pier in Central.

Midway through the run I got this email from Jacalyn.

It’s nice that Jacalyn puts her sign off in a different font with a different colour. I like that.

I don’t know why, but reading the word devastated made me feel sad for Jacalyn. I did a little bit of thinking and then I thought “Maybe I could try to figure out a way to convert these scanned PDFs”.

I didn’t include it in the picture above, but Jacalyn had her phone number in her email signature. It looked like an Australian mobile phone number. So I called her.

“…Hello” she answers cautiously. It was 830 PM in Hong Kong, and 1130 PM where she was.

“Hi, I’m Angus, we’ve been emailing each other about the bank statement website”

“Where are you calling from”

“Hong Kong”

“Oh okay”

We then talked about her situation. She had a lot of clients that were sending her paper statements and getting through them manually would take her a very long time.

“I think I can process them, but I’ll need two weeks to get something ready. Can you wait that long”

“Yes yes yes!”.

For the next few days I mess around with Tesseract, an optical character recognition library and get something sort of working for scanned bank statements.

Started Blogging

I think I started blogging in 1998, in a class at school we were taught how to use a web builder created by homestead.com. I created a blog, and then forgot about it. Many many years later that blog is gone. Kind of sad really, it would be nice to read the blog posts I wrote when I was ten.

After that I had a blog on netfirms.com, that has also gone away but I still have the HTML files and flash animations from it. Then I had a wordpress blog at ballerindustries.com. One day I just didn’t feel like paying for it and it went away. That’s on the internet archive.

Around this time a friend of mine started blogging about how crypto exchanges work. He put a lot of work into his posts and a lot of people read them. I started to think “Maybe blogging is a good way to get people to use this here Bank Statement Converter”.

I did some reading and decided “Yes, I will make a blog”. The first thing I wrote about was getting an upset email from Jacalyn.

End of Month Numbers

Users

159

Revenue

$1829 HKD

Monthly Recurring Revenue

$984 HKD

Ad Spend

$10200 HKD

September 2021, A Strange Dinner

For some reason, Dad messaged me and told me he wanted to get dinner with Uncle Ken. Ken is very loosely related to me and my Dad.

Depressing Dinner with Ken 2007 Edition

The last time I saw Ken was in January 2007. At the time I was studying Computer Science at university and Ken was working for the Hong Kong government in some information technology related job.

Dad probably thought “Ah the boy is a computer man, Ken is a computer man. I should introduce him to Ken to help him do business networking”.

We went to dinner somewhere in Wan Chai and immediately Ken didn’t believe that I was related to my Dad.

“But you don’t look like him at all? Danny are you playing a trick on me, is this one of your colleagues?”

“Ken, this is really my son okay?”

“...alright Danny, but I know you’re a trickster”

Ken talks about working in IT, he paints a bleak picture and spends the whole dinner trying to talk me out of it.

“Angus be a doctor instead, that’s much better”

I tell Ken I want to be a programmer and I want to work in Hong Kong when I graduate.

“Well that’s not going to work. Look I shouldn’t tell you this, but no one is going to hire you here. You’re half Chinese, which basically means not Chinese, and we don’t like to hire non Chinese people in Hong Kong”

I didn’t really believe what Ken was telling me, and there were lots of subtle signs that Ken was a bit of a loser. I’ve been to many dinners, but I’ll never really forget that one. Dad was hoping to help me with my career as a computer man, but instead some jerk tried to talk me out of the world of computers.

Depressing Dinner with Ken 2021 Edition

I don’t really know why Dad wanted to see Ken, and I didn’t really want to go. I didn’t like the guy the first time I met him and I was planning to never see him again.

We went over to Ken’s house for dinner, his Mum and Sister are there too. I can’t remember what we talked about but Ken asks me what I’m up to. I tell him I quit my job and I’m making a PDF converting app. I tell him it’s not really going very well, and then Ken just nods and talks about something else.

I zoned out a bit at the dinner and then I started thinking “Did Dad organise this dinner to tell me not to be like Ken? Am I on the path to being like Ken? Do I need to change something?”

I started thinking about stopping work on Bank Statement Converter and going back to working for a bank.

Turning Off Ads

Since launching I have brought in $6263 HKD in sales and I have spent $35,960 HKD on Google Ads.

I had to turn off the ads.

This was psychologically difficult to do. I knew that once I turned off the ads, traffic to the website would drop massively. On September 24 2021 I stopped running the ads.

The unique visitor count went from about 70 a day to 15 a day. I was expecting it to drop to 1 or 2 users a day, so in a way this was a good thing.

Hacker News Second Chance List

One day I got a bunch of OutOfMemoryErrors. I did some profiling and found that the app was allocating a ton of memory in certain situations. I did a bunch of stuff to reduce the memory usage. Since I had a blog I thought “people might be interested in reading what I did”. So I wrote a blog post about it.

I then submitted the post to Hacker News, and it got onto the front page. This led to a few days where I had hundreds of visitors. It also led to three new registrations. Loads of people read the blog post, but not many went and tried the app after.

Still it probably had a good impact on my Google search rankings.

End of Month Numbers

Users

116

Revenue

$2057 HKD

Monthly Recurring Revenue

$1607 HKD

Ad Spend

$2760 HKD

October 2021, Zero Ad Spend

Raising Prices

At this point, if you gave me $19.99 every three months, I would let you convert an unlimited number of PDFs. I was starting to think the pricing was too low. I raised it to $14.99 billed month or $89.99 billed yearly.

I had more than doubled prices and People didn’t seem to care. Good, more money for me.

Enter Eugenio

One day a man named Eugenio who works at a law firm in London emailed me. He complained that the text on my website was vague and he asked me a lot of questions. I replied to all his emails and there were a lot of them.

He liked the app, and he told me “Good job”. Then he bought a subscription. A few days later he said “Angus, this app is too cheap, you should charge me seat pricing

I did some thinking and then figured out a way to let people buy multiple subscriptions so that they could add in other people they worked with. I told Eugenio and then he bought two more seats. Thank you Eugenio.

Eugenio could have shared his login credentials with his colleagues, but instead he decided to give more of his law firm’s money to me. Thank you Eugenio.

End of Month Numbers

Users

48

Revenue

$3681 HKD

Monthly Recurring Revenue

$2422 HKD

Ad Spend

$0 HKD

November 2021, Professional Marketing

I turned off the ads in September 2021 and the next month I made even more money. This wouldn’t have happened if I hadn’t raised prices. Also, a big portion of the revenue from the previous month came from one customer. In November 2021 I was expecting to bring in less money than the previous month.

Enter Professional Marketer

One day I got a tech support email from some guy in South Africa. I notice he’s a ‘digital marketer’. I ask him if we can talk and discuss ideas to help me grow Bank Statement Converter. We talked and he suggested that he runs Google Ads for me.

No thanks. It’s too expensive. Also I suspect he won’t be able to do much better than I did. He then suggests we run a cold email marketing campaign using Lemlist. Sounds more interesting. I then agreed to pay him $600 USD for 20 hours of marketing work. I signed up for LemList and gave him the login details.

A week goes by, and he hasn’t replied to my email or done anything with LemList. I prod him with an email and he makes some excuse about power outages disrupting his work. He then inputs some contacts into LemList and sets up a template.

Two more weeks go by, and he hasn’t done anything new in LemList. I fix the template for him, and schedule the emails to go out. It annoys me that I have to finish his work for him. Also I assess that the work he’s done would take me about three hours to do. He has done about three hours of work in the space of three weeks.

I send him this email:

Hi XYZ,

Overall I got the impression you don't really have the time to take me on as a client. There were long gaps between our emails, which led to bad results. I think in the end we were only able to send out about twenty emails.

Last month Bank Statement Converter brought in about $450 USD in revenue, so I can't really afford to spend money that doesn't yield results.

If you'd like to talk more about this we can get on a call.

Angus

He never replied to the email, I think he knows he did a crap job and was embarrassed. Or, more cynically, maybe he was just happy to pull $600 USD out of me.

I learnt a lesson from this, don’t hire someone until you know how to do their job. Otherwise it’s hard to tell whether they’re good or not. It also made me think poorly of people who work in marketing.

Merging descriptions

Around this time the resulting data we would send out looked a bit like this:

Date

Description

Amount

Balance

Jan 1

Horse medicine from

-100

1000

The world famous horse medicine company

Jan 2

Delicious hamburgers

-20

980

Bought next to the petrol station

Jan 3

Salary

500

1480

From Credit Suisse

Not too bad, but it was annoying that the description spreads across multiple lines. I did this because it appeared like that in the PDF, and it was hard to figure out how to join the descriptions together.

Users would tell me they didn’t like the descriptions spread across multiple rows. I started fixing the results for specific banks. Then I thought “Why not just aggressively merge the descriptions up?”.

Algorithm

  1. Read a row
  2. Is there a DATE, AMOUNT or BALANCE value in that row?
  3. If there isn’t, append the description column to the previous row’s description.
  4. Go back to step 1.

Date

Description

Amount

Balance

Jan 1

Horse medicine from The world famous horse medicine company

-100

1000

Jan 2

Delicious hamburgers Bought next to the petrol station

-20

980

Jan 3

Salary From Credit Suisse

500

1480

That’s much better. The algorithm doesn’t work for all bank statements, but it works for most. We can configure a special row merging strategy for those bank statements and cover the common case with this strategy.

End of Month Numbers

Users

104

Revenue

5231 HKD

Monthly Recurring Revenue

3282 HKD

Ad Spend

0 HKD

December 2021, Getting Greedy

Advent of Code

I started to get bored with coding Bank Statement Converter. Instead I spent most of the month learning Rust and solving Advent of Code puzzles. I really enjoyed the speed of Rust, but I did not enjoy fighting with the Rust compiler.

I think it’s really cool that Rust enforces memory and thread safety through its compiler. However I did not enjoy coding in Rust.

Creating an NFT

Around this time some crypto bros appeared and asked me if I would help them create an NFT collection. They said I could be the CTO. I got greedy and agreed to do it in exchange for a portion of the revenues generated from selling the NFTs.

My job was basically all tech related stuff:

  1. Creating the marketing site
  2. Creating the smart contract
  3. Merging the layers into PNGs + metadata

This NFT project dragged on for months, and by the time we were done the NFT market had collapsed. So we decided to pause until the market recovered. It still hasn’t recovered, and probably never will. I’m embarrassed that I was part of this, and I wasted a large amount of time working on it.

Cold Emailing

I decided to take over the cold emailing from the marketing guy. I started sending out one email every 20 minutes during an 8 hour window. The first email goes out on December 21st 2021. I got my first reply from someone a week later. The reply is strange:

Thank you, Angus.

I would like to use your software & promote it to other accountants.

Regards,

I replied to this, but he didn’t respond to me. I just checked and this person has never signed up for Bank Statement Converter. Aside from strange messages I also got a few angry replies.

I don’t know who u r and ur emails look like scam! If u have something to offer, talk straight.

Kindest Regards,
[NAME]

This guy was from Canada and he had his phone number in his email signature. I called him three times but he hung up on me every time as the phone was dialling.

Most people ignore the emails I send out. After two months of cold emailing people I was able to sell two subscriptions. It doesn’t seem to be a very effective marketing strategy for me.

End of Month Numbers

Users

112

Revenue

$7490 HKD

Monthly Recurring Revenue

$4612 HKD

Ad Spend

$0 HKD

January 2022, Wasting Time

All I did was fix conversion issues that customers reported to me. The rest of my time went to the NFT project.

Google Suite Ban

One day I get this message from Google:

The Google Account angus@bankstatementconverter.com is now disabled. It looks like it was being used in a way that violated Google's policies.

I assume I was banned for sending out too many unsolicited emails. Cold emailing isn’t against Google’s policy, but it is if it’s automated and the volume is too high.

Lemlist recommends you send out emails every 20 minutes in an eight hour window, so you don’t get banned by Google. I was sending out emails around the clock:

  1. 10 AM to 6 PM to users in South Africa
  2. 10 AM To 6 PM to users in Australia
  3. 10 AM to 6 PM to users in North America

This was annoying, but it really was my fault. I think LemList should put tighter restrictions on their customers. I reckon Lemlist should make sure their customers know what will get them banned from Google and strongly advise they don’t set up overly aggressive campaigns.

I decided to stop cold emailing users. I cancelled my Lemlist subscription and bought a FastMail subscription. It was very easy migrating my emails from Gmail to FastMail.

End of Month Numbers

Users

178

Revenue

$10050 HKD

Monthly Recurring Revenue

$6974 HKD

Ad Spend

$0 HKD

February 2022, NFT Metadata

Our NFT project was fancy watch themed. We hired people to make the layers for the watches, but we forgot about the metadata. That meant we had to go through the hundreds of layers and assign metadata values.

I don’t know anything about fancy watches, so I had to get on a call with a guy who owns a watch store. I’d share my screen, show him the layer, and then he’d think up attributes for that layer. Attributes like patina and lightly used. Doing this made me like watches a little bit more, but I’m still not a fan of luxury products. I would never buy a fancy watch or any other luxury product.

Preventing Account Abuse

A fair amount of people were creating multiple accounts to get more free credits. This annoyed me. I realised I could block people from the same ip address from creating multiple accounts. So I did. This led to people getting blocked from creating an account and then buying a subscription. So I guess that improved conversion rates.

Replaced Monit with systemctl

I was using Monit to automatically restart my app when it crashed. One day I realised I could use systemctl instead.

Systemctl is short for “system control”. Cool guys like to pronounce it as “system cuttle”. This makes it sound like Linux systems are controlled by a cuttlefish.

I use Ubuntu Linux, and systemctl is bundled with that. It’s basically a part of the operating system so it will be running. I figured I might as well use systemctl and then I could delete Monit. That would mean I would have one less process running. So I did that. Thank you system cuttlefish.

End of Month Numbers

Users

178

Revenue

$11926 HKD

Monthly Recurring Revenue

$9040 HKD

Ad Spend

$0 HKD

March 2022, Enter Taxman

I made six Git commits this month. I was busy with the NFT project.

Australian Tax Office

Someone from the Australian Tax Office (ATO) emailed me and wanted to get on a call. They told me they’re from the financial crimes department. The ATO has the power to get bank records from any business in Australia if they suspect that business is doing a financial crime.

Usually the banks will give the ATO CSV or Excel files, but some banks send over enormous PDFs instead. The ATO wanted to use Bank Statement Converter to deal with the enormous PDFs. I tell the ATO their idea is a grand idea, and I’d be happy to sell them a subscription.

Now, at this time a user can buy an unlimited subscription for $90 a year. That means even a cashed up organisation like the ATO would only be paying me $90.

That ain’t right! This leads me to start thinking about how to get more money from bigger customers.

A bit later the person from the ATO tells me they’re worried about data privacy and security concerns. They ask me if the application is end-to-end encrypted. I tell them it’s not because end-to-end encryption means even my server cannot read the PDF, which would make it impossible to process the PDF.

I suggest that I make them an offline version of Bank Statement Converter. That way it’ll run on their machines and the data never leaves the ATO. Surprisingly they did not like that idea. They tell me updating offline apps is a pain and they much prefer cloud solutions.

The conversation fizzles out and I fail to sell my services to the Australian Tax Office. What a shame.

End of Month Numbers

Users

209

Revenue

$11671 HKD

Monthly Recurring Revenue

$11049 HKD

Ad Spend

$0 HKD

April 2022, Word of Mouth

I have a customer who emails me every few weeks asking me to help them login. This is interesting because I only let people login with Google. All they have to do is press a button. I think they’re often using new computers and they often forget which Google account they bought a subscription with.

I always help them login, it’s not too hard, I just copy and paste the answer I gave them from a few weeks before.

Corporate Unlimited Plan

My discussions with the Australian Tax Office made me realise I need to figure out a way to get more money from the bigger customers. I came up with a Corporate Unlimited Plan. It costs $45 a month or $270 a year. This lets big customers set a domain name and then everyone with an email address under that domain has an unlimited plan with Bank Statement Converter.

Then I sat back and waited for the money to come rolling in.

Word of Mouth

But the money did not come rolling in. Not many people bought the Corporate Unlimited Plan. It’s much cheaper to create one account and then share that login with all your colleagues.

One person does buy a yearly corporate unlimited plan, they’re friends with the forgetful customer I talked about at the start of this chapter. This is the first time I see someone buy the app through word of mouth. I suspect this happens quite a lot, but it’s hard to track.

IRS Tax Deadline

In 2022 the deadline for filing a tax return with the IRS was May 2nd 2022. This is why April was such a good month, lots of Americans were playing around with bank statements. The tax return filing deadline is around the same time every year.

End of Month Numbers

Users

215

Revenue

$19058 HKD

Monthly Recurring Revenue

$13184 HKD

Ad Spend

$0 HKD

May 2022, NFT Market Collapses

NFT Project Ends

The NFT market collapses and me and the crypto bros still haven’t launched our NFTs. Damn. The bros decide to delay the launch until the market comes back. I suspect the project is dead and the NFT market will never return.

The bros I worked with all had full time jobs, I was the only one working on this full time. That was a bad idea.

It was also a bad idea to do this because I did not believe in NFTs. I knew the NFTs had no value, but I agreed to help for the easy money. Selling something I knew has no value made me feel like a scammer.

I would have been better off getting paid for this instead of taking equity, however I left my job to be an entrepreneur. Getting paid for hourly work wasn’t the goal.

Password Reset

Password reset flows are always a pain in the butt to implement. So I just didn’t create one. Whenever someone asked me to reset their password I manually bcrypted their password and hacked it into the database. Eventually I got fed up with that and implemented a password reset flow.

I only mention this because I think it’s a cool way to save development time. A lot of features you think are essential for launch probably are not. Dom and I launched Bank Statement Converter without a database and without the ability for people to register accounts.

Crisp Chat

I was listening to YCombinator talks by the founder of Intercom. Intercom is a chat widget you can embed on your website, it’s a nice customer support tool.

I thought “I should add that in, I like talking to my users”. Intercom turned out to be very expensive. So I used a freemium alternative called Crisp Chat. I highly recommend it. I’ve done a lot of sales conversations and customer support work through Crisp Chat. I’m still on the free tier, but one day when I need one of their premium features I will be happy to pay for it.

End of Month Numbers

Users

181

Revenue

$21008 HKD

Monthly Recurring Revenue

$15792 HKD

Ad Spend

$0 HKD

June 2022, Enter Maxwell

One day in June 2022 I got a message from a guy called Maxwell. He asked me a few questions about Bank Statement Converter. Then he tells me he runs a software as a service (SaaS) business for accountants.

“Very interesting” I say, even though it is not interesting.

This is just something you have to say while doing business from time to time.

Maxwell tells me he wants something known as an application programmer interface (API). He wants this so that his application can send PDFs to my application and receive back data in Javascript Object Notation (JSON).

I tell him “Maxwell, that is a fine idea, and I will be happy to do it”. That was sort of a lie, I was willing to do it, but it didn’t make me happy.

In business sometimes you have to pretend things make you happy even when those things have no impact on your happiness.

In fact Bank Statement Converter was designed using what’s known as a “Client Server Architecture”. This means that the app is actually two apps. How about that!

One app draws pictures and tells you where to drag your PDFs. That app is known as the user interface. The other app is a much more serious guy. This app, or guy, only cares about data. You can send it data, and this guy will send you back some other data. This guy is known as the server. The server’s main job is taking in PDF files and sending back CSV records.

Ah but wait. Maxwell wanted JavaScript Object Notation instead of CSV. He also wanted the resulting data to have predictable field names. You see I just grabbed the headings from the PDF and put them into the CSV. Take a look at examples below:

Example 1

Date,Narration,Deposit,Withdrawal

10 Mar,Sushi,,100.00

11 Mar,Cola,,4.20

Example 2

Date,Description,Credit,Debit,Balance

10 Mar,Sushi,,100.00,200.00

11 Mar,Cola,,4.20,195.80

As a lazy person, I suggested to Maxwell that I do the same thing with the JSON data. He did not like this idea at all. He wanted predictable field names. What a drag. I did some thinking and I thought to myself “Well I guess I could do it. It’s not impossible”

Eventually I ended up sending JSON data like this:

Maxwell messaged me on June 29 and by July 1 I had a JSON API for him to try out.

End of Month Numbers

Users

234

Revenue

$19389 HKD

Monthly Recurring Revenue

$16811 HKD

Ad Spend

$0 HKD

July 2022, Ask for the Sale

I spent June and July resolving document parsing issues that Maxwell and his team discovered. I slowly realised this sort of work could go on forever. I decided I needed to start charging Maxwell to see if he was a serious customer or not. He seems serious but he had not given me any money yet.

I sent over this email:

Then I went to meet some friends for drinks.

You see in business, it is very important to meet your friends for drinks and perhaps get drunk. No one knows why this is a good idea, but everyone agrees it is a good idea.

After many drinks, I get a message from Maxwell asking to talk with me on Skype. I take the call. He says he doesn’t really think he should pay, because the work I’m doing to fix these documents can apply to other customers as well.

I tell him that’s true, but it’s a lot of work. I also tell him I’ve factored in a discount to account for that. We talk a bit more, we also roughly discuss a contract he’d like me to sign.

Then he says something about being limited to 10,000 documents a month. We count pages in Bank Statement Converter instead of documents. We do this because some PDFs have a ton of pages and some customers join together multiple PDFs into one file. I tell Maxwell “I think the original agreement was 100,000 pages per month, not 10,000 documents”.

This angers maxwell. I tell him why we go with pages and he says “We’re not going to join together PDFs and send them over”. I decided to drop the requirement and let him be limited to 10,000 documents a month.

I make a mental note to let him know if I see any document joining or mega PDFs.

We got to an agreement pretty quickly. Maxwell will send a big dump of documents, and then I’ll figure out how much to charge them for custom parsers.

Raising Prices

Around this time I decided to start charging based on usage. It doesn’t really make sense that a customer who converts thousands of documents a day pays the same as a customer who runs one a month.

I split the pricing into three plans: Starter, Professional and Business. The plans have monthly and yearly options. Each plan gives you an amount of credits per month or per year.

The conversion ratio drops a bit, but the higher cost makes up for this. The average revenue per user goes up. Very nice.

End of Month Numbers

Users

357

Revenue

$19837 HKD

Monthly Recurring Revenue

$18139 HKD

Ad Spend

$0 HKD

August 2022, Getting Paid

Document Analysis

At the start of the month Maxwell sent me a large number of bank statements. After that I created a tool that used text, positions and images in the first page of a document to group the PDFs together. From there I figured out how many Customer Parsers need to be created.

In the dump we came across a lot of PDFs that aren’t bank statements. Things like car loan statements and mortgage statements. Maxwell agrees to ignore those. Eventually we determine we need to create 36 Custom Parsers. I asked for half the money up front and the other half on completion and sent over a Stripe payment link.


Maxwell sends it over. Okay he’s a serious customer, good!

Ambiguous Amounts

For some reason the American banks like to group their transactions into multiple tables. These tables have headings like “Checks”, “ATM Deposits”, “Cash Deposits”, “Withdrawals”, “Fees”, “ACH Withdrawals”, “ACH Deposits” and so on.

These tables will have the columns “Date”, “Description”, “Amount”. Fine whatever, no problem so far. But, there is a problem. Sometimes they will not put a minus sign in front of the debit amount. So you’ll have a table with the heading “Withdrawals” and all the amounts in that table will be positive.

Now as a human reading that table you know “Ah well these are withdrawals, so they’re debits”. Bank Statement Converter wasn’t smart enough to do that. This meant, for certain US banks, all the transactions came out with positive numbers, which made them look like credits.

What a pain eh. I wrote some code that grabbed the lines before the heading of a table. Then using those lines it determined whether or not the Amount column was actually a debit column. The algorithm goes something like this:

  1. Capture the lines before a table heading.
  2. Is there an amount column in the header of the tablee?
  3. Are all the amounts in the amount column positive?
  4. Is there text in the preceding lines like “Withdrawal, Debit, Fee”?
  5. If #2, #3 and #4 are true. Change the Amount column to a Debit column. Put a minus sign in front of all the amounts.

SerializedParser

At this time all my customer parsers were Kotlin class files. This meant whenever I wanted to support a document, or fix an issue with a custom parser I needed to write code and redeploy the application. It takes about 5 minutes for my tests to finish running, this means I can get something into production in about 5 minutes. Pretty fast, but writing the code takes at least an hour, even if it’s something trivial.

I started thinking about creating a UI that lets me draw a rectangle on the page. This rectangle says where the data we care about is. Then some code automatically figures out how to extract that data.

Before doing all that I spent some time creating a JSON data structure that represents the rules for parsing a bank statement. I can then store this JSON data in the database. Once that’s done I can create/edit custom parsers while the app is running.

This is really cool because it means I can get a document fixed in a few minutes as opposed to one hour.

End of Month Numbers

Users

328

Revenue

$62596 HKD

Monthly Recurring Revenue

$21701 HKD

Ad Spend

$0 HKD

September 2022, Applying for YCombinator

Document Fixing

Spent most of the month fixing documents for Maxwell and other customers. Maxwell’s documents are mostly from the US and Canada. Over the last few months I have mostly been fixing documents for him.

As a result of this, customers in the US and Canada start converting a lot better. When I say “converting better” what I mean is a larger percentage of users from the US buy a subscription. This is good.

Applying for YCombinator

I was pretty happy to get this email. They said I was in the top 10%, but who knows maybe they say that to everyone. I quickly filled in the application and recorded a video.

Maxwell Subscribes

At this point, Maxwell still wanted me to fix a lot of documents and his team hadn’t gone into production with my API. I decided it was the right time to ask him to start a monthly subscription and I sent him a Stripe payment link. He agreed and says he will pay the subscription midway through the month. Good.

End of Month Numbers

Users

448

Revenue

$46736 HKD

Monthly Recurring Revenue

$37521 HKD

Ad Spend

$0 HKD

October 2022, Document Fixing

User Referral Program

I spent about a week implementing a user referral scheme. I set it up so that you get free credits for every user you refer to Bank Statement Converter. At the time of writing only 45 people have used this feature. I think user referral schemes can be great for some applications, but it hasn’t worked out great for Bank Statement Converter.

End of Month Numbers

Users

341

Revenue

$46846 HKD

Monthly Recurring Revenue

$40730 HKD

Ad Spend

$0 HKD

November 2022, Going to Australia

Hong Kong Fintech Week

A friend of mine gets me a free ticket to Hong Kong Fintech week. This is the first time I’ve been to a conference. I get the feeling I’m supposed to wander around telling people about my start up and hearing about their start up.

I wander around talking to people, but no one really seems to need a bank statement converter. Lol. Sam Bankman-Fried is one of the keynote speakers. I didn’t bother watching it but I think he did it from home via Zoom. This would have been one of his last public appearances before it was discovered he was taking part in fraud.

After the conference I went to my Dad’s house and noticed my brother looked a bit like Sam Bankman-Fried. Four days after this Facebook post FTX collapsed.

You see in business, you should not let my brother impersonate you. It is extremely bad luck.

I talked to a lot of people at the conference, and it seemed like most people there did not want to talk to me. Some people talked to me, but only because they wanted to try to sell me the services of their start up. I did enjoy my time at the conference.

There were a lot of talks at the conference too, but none of them were interesting. It was basically just senior bankers taking part in management speak. I got the feeling all they wanted was a picture of them on stage for their LinkedIn profile.

I collected a lot of business cards at the conference and emailed everyone afterwards. Zero people replied to my emails. I must be the worst emailer in the world, because my email response rate is under 1%.

Going to Australia

My cousin was getting married and at the same time Hong Kong had relaxed covid restrictions. This meant I could leave Hong Kong without having to quarantine myself in a hotel for multiple weeks. I hadn’t gotten on a flight for almost three years, so I was very happy to get out of Hong Kong.

When I was in Sydney I realised I had a lot of customers there, so I emailed all my customers in New South Wales asking if they wanted to meet for a coffee.

This guy was about eight hours away from Sydney, a bit far away for me.

This was from Jacalyn, the user who emailed me about scanned bank statements in August 2021. We talked a lot via email after that. I attended the ABN Coffee Club meet up and then hung out with her and a friend of hers. We talked about accounting and accounting software. I didn’t really understand a lot of it, accounting is such a mysterious job to me.

Afterwards I told Jacalyn I was getting driving lessons because I hadn’t driven for six years.

“Do you want to drive my car back to the city?”

“Sure”

It was very nice of Jacalyn to let me drive her car. It was a Suburu SUV, a much bigger car than what I was used to. We drove to the city and I had trouble changing lanes to get to where I wanted to go. We ended up at Milson’s point and I said “Let’s just park here, I’m too scared to drive around in the city”.

I also met up with a customer called Tony. He said the app works as he expects and was happy with everything. That’s good I guess, however I was hoping to find some new killer feature/app to build.

End of Month Numbers

Users

392

Revenue

$56932 HKD

Monthly Recurring Revenue

$43914 HKD

Ad Spend

$0 HKD

December 2022, Anonymous Purchasing

Allowing Anonymous Purchases

From time to time I would get an email from someone asking me how to buy the app. I’d tell them “Create an account, and then go to the subscribe page, then click one of the plans”.

This was happening because I didn’t show a link to the pricing page until a user created an account and logged in. I started thinking “Why not just let people buy immediately, even without an account”. One thing I always say is “If you want someone to do something, make it as easy as possible for them to do it.”

When I was a working stiff, I’d often get messages from colleagues saying

“Please approve my pull request.”

They wanted me to approve their pull request, but they didn’t make it as easy as possible for me to do so. One improvement would be including the link.

“Please approve this pull request. [LINK]”

Then I don’t have to remember the name of their repository, find it on GitHub and find the pull request they made. Let’s get back to talking about my anonymous purchase feature.

Plan

  1. Show the pricing page to anonymous users.
  2. Change the payment API so that we can accept payments from anonymous users. This meant removing the requirement that the payment API has an Authorization header.
  3. When someone buys anonymously, store their email address in the anonymous_purchase table.
  4. When someone buys anonymously, send them an email telling them to register. Stripe requires users to provide an email address when buying.
  5. When a user registers, check the anonymous_purchase record. If their email is in there, give them the appropriate amount of credits for the plan they purchased.

Before coding a feature I usually break it up into steps like that. Read it and think “Yes very good that makes sense”. Then I might break it up into little tasks. Here’s how I broke down the above plan into little tasks

Surprisingly tons of people buy before creating an account. This is really strange to me. If I can try out a product I will try it out before buying. I guess some people think “Bank Statement Converter? Hell yeah! Take my money right now Angus Cheng”. Or perhaps someone recommended it to them, gave them a demo and they thought “Very nice, I’m going to buy that right now”.

12 Apps of Christmas

Jacalyn helped me get featured in an Australian Facebook group full of accountants. This led to quite a few sales. Thanks Jacalayn! For a long time I was trying to figure out where accountants hang out, turns out it’s in Facebook groups. Makes sense.

The rest of the month I spent in France visiting my Mum, Sister and her family. It was nice.

End of Month Numbers

Users

356

Revenue

$58004 HKD

Monthly Recurring Revenue

$48959 HKD

Ad Spend

$0 HKD

January 2023, Social Media Monitor

Social Share Buttons

I got the idea to implement social share buttons. They’re pretty easy to implement, so I figured it couldn’t hurt.

In the thirteen months since I implemented this feature the social share buttons have been pressed 32 times. Those 32 button clicks resulted in one person signing up. That one new sign up resulted in $0 of revenue.

So there you go, a day’s worth of work resulted in one new person signing up and $0 in extra revenue.

SocialMediaMonitor.io

At the end of the month a friend wanted to build an app for social media monitoring. He got the idea from MentionTools.com he saw they were doing well and thought “We could do that too”. I liked the idea, and figured it would be something people wanted. I was also excited to work with my friend.

My friend is mostly a backend developer, just like me. I didn’t want to build the UI, so I once again pitched the idea to Dominic. He was in Hong Kong for about a week so I met up with him and Kris and presented the idea to him while going on a hike to an abandoned resort.

Dom liked the idea and agreed to build the UI for it. Great!

End of Month Numbers

Users

442

Revenue

$66873 HKD

Monthly Recurring Revenue

$50408 HKD

Ad Spend

$0 HKD

February 2023, I Sleep

Spent the month working on Social Media Monitor. Supported documents and fixed a few bugs in Bank Statement Converter. Didn’t do anything significant though.

End of Month Numbers

Users

506

Revenue

$62457 HKD

Monthly Recurring Revenue

$57820 HKD

Ad Spend

$0 HKD

March 2023, Monitoring Ends

Not much happens with Bank Statement Converter.

Dom Leaves

On March 9 2023 Dom leaves Social Media Monitor. Kris and I don’t really want to do the UI so we just kind of leave the project dormant. I’ll talk a bit more about Social Media Monitor in the Failed Projects chapter.

End of Month Numbers

Users

602

Revenue

$66839 HKD

Monthly Recurring Revenue

$63053 HKD

Ad Spend

$0 HKD

April 2023, Service Level Agreement

Bank Statement Converter has a very strong month. This is the deadline for filing taxes with the IRS falls in April.

Service Level Agreement

When I started talking with Maxwell, he wanted me to sign a Service Level Agreement before integrating with Bank Statement Converter’s API. I said “Yeah sure, get it over to me and I’ll have a look”. I guess Maxwell got too busy, because he started using my API and paying me before sending me the agreement to sign.

Then in April 2023 Maxwell contacted me with a rough draft of the service level agreement. It says:

In the event that you Angus Chen not able to support the Bank Statement API the source code, full source code, instructions and infrastructure and everything needed to continue running the Bank Statement Converter software would be transferred over to XYZ with the following stipulations:

1)  Failure to support  which triggers this agreement  is defined when most existing supported PDF’s are no longer supported and do not function after 5 full business days. Meaning that the API stops working for the majority of the bank statement conversion to PDF and the software is deemed inoperable.

2) XYZ is granted rights  access in perpetuity to the full source code and infrastructure and documents in the event that BankStatementConverter.com can no longer support the software. The software is granted "as is”. XYZ may utilize resources to bring the software back up online and make it functional

3) XYZ will not sell the software independently, rather is part of the XYZ software in the event that a copy of the source code is delegated to XYZ .

4) XYZ will pay a royalty of  $0.07 for every scanned bank statement that utilizes  Bank Statement Converter technology.

5) XYZ is not obligated to support outside business of Bank Statement Converter.com. In the even that XYZ does support other non XYZ Customers or operations, XYZ will pay $0.07 royalty to Angus Chen

6) XYZ is responsible for infrastructure and development costs.

Immediately I knew I didn’t want to sign this agreement. I spent a week thinking about an agreement that worked for me and dealt with Maxwell’s concerns. I came up with this:

1. XYZ will pay Bank Statement Converter $X every month until 30 September 2027.

2. XYZ will be limited to converting 10000 PDFs per month

3. XYZ will not join together multiple bank statement PDFs into one larger PDF.

4. XYZ will pay a Bank Statement Converter a $X deposit. This deposit will be refunded within 14 days after 30 September 2027. If XYZ wishes to terminate this agreement before 30 September 2027, they will forfeit the deposit.

5. Bank Statement Converter will hire a full time employee to do support and development work.

6. In the event that Bank Statement Converter decides to shut down, XYZ will have the opportunity to buy the intellectual property for $X

7. XYZ has the Right of First Offer. Before the Bank Statement Converter business can be sold to a third party, XYZ must be allowed to make a counter offer. If XYZ's offer is greater than or equal to the third party's offer it must be accepted.

8. If the Bank Statement Converter API or customer support is not functioning to the standard below, Bank Statement Converter will pay a penalty to XYZ of $X. This penalty can be invoked a maximum of one time per month.

API Penalty

XYZ may invoke a penalty on Bank Statement Converter if no documents can be converted for more than 36 hours.

Customer Support Penalty

XYZ may invoke a penalty on Bank Statement Converter if Bank Statement Converter does not reply to support messages within three business days.

Maxwell didn’t like this agreement. We couldn’t come up with a good agreement so we continued working together without one.

End of Month Numbers

Users

559

Revenue

$96842 HKD

Monthly Recurring Revenue

$72489 HKD

Ad Spend

$0 HKD

May 2023, I Sleep

Nothing special happens with Bank Statement Converter. I fix issues with documents as always.

AngusForm.com

I get the idea to automate some real world processes. Things like applying for a driver’s licence. In Hong Kong most people fill in a form, print it out, sign it and take it to a government office to apply for a driver’s licence.

I started thinking “What if I provided a service that would do this for them, so they can apply for a licence online and someone from my company will hand in the form”.

I’ll talk more about AngusForm.com in the Failed Projects section.

End of Month Numbers

Users

553

Revenue

$86179 HKD

Monthly Recurring Revenue

$74452 HKD

Ad Spend

$0 HKD

June 2023, I Sleep

Supported documents and worked on AngusForm.com

End of Month Numbers

Users

748

Revenue

$81921 HKD

Monthly Recurring Revenue

$74294 HKD

Ad Spend

$0 HKD

July 2023, I Sleep

Supported documents and worked on AngusForm.com

End of Month Numbers

Users

1299

Revenue

$75793 HKD

Monthly Recurring Revenue

$76392 HKD

Ad Spend

$0 HKD

August 2023, I Sleep

Supported documents and work on AngusForm.com

Customer Support Sim

I spend a lot of my time replying to customer support emails and messages for Bank Statement Converter. In a way it’s kind of fun. This makes me think “What if there was a simulation game where you played as a customer support agent?”

I’ll talk more about Customer Support Sim in the Failed Projects section.

End of Month Numbers

Users

933

Revenue

$97944 HKD

Monthly Recurring Revenue

$83218 HKD

Ad Spend

$0 HKD

September 2023, Custom Pricing

Custom Pricing

A lot of people start asking me for high volume pricing. Sometimes they want pricing in their own currency. So I created an API that lets me create custom pricing so that I can define the number of pages, the currency and the payment amount.

It then gives me a URL I can send a user to pay for their plan at that price. This saves me an hour or two of work every month or so. Somewhat useful I suppose.

End of Month Numbers

Users

1117

Revenue

$109219 HKD

Monthly Recurring Revenue

$91448 HKD

Ad Spend

$0 HKD

October 2023, I Sleep

Didn’t do much.

End of Month Numbers

Users

956

Revenue

$128150 HKD

Monthly Recurring Revenue

$98979 HKD

Ad Spend

$0 HKD

November 2023, Busty Barrister

I started working on a visual novel game where you play as a barrister in Hong Kong. It’s called Busty Barrister Barbara. I’m still working on this at the moment so it doesn’t belong in the Failed Projects or Successful Projects sections yet.

You can play it here:

https://ballerindustries.itch.io/busty-barrister

End of Month Numbers

Users

884

Revenue

$142569 HKD

Monthly Recurring Revenue

$107747 HKD

Ad Spend

$0 HKD

December 2023, Busty Barrister

I supported more documents and worked on Busty Barrister Barbara.

End of Month Numbers

Users

997

Revenue

$130019 HKD

Monthly Recurring Revenue

$109979 HKD

Ad Spend

$0 HKD

January 2024, I Sleep

I supported more documents and worked on Busty Barrister Barbara.

End of Month Numbers

Users

1373

Revenue

$134701 HKD

Monthly Recurring Revenue

$126130 HKD

Ad Spend

$0 HKD

February 2024, I Sleep

I supported more documents and worked on Busty Barrister Barbara.

End of Month Numbers

Users

1361

Revenue

$161333 HKD

Monthly Recurring Revenue

$142338 HKD

Ad Spend

$0 HKD

Failed Projects

Let’s Get Fiscal (2011)

The second game I created for the Xbox Live Indie Game store. Instead of making a sequel to Get Rich or Die Gaming I made a beat ‘em up similar to Streets of Rage 2. I spent over a year on the game and I think it made about $2000 USD.

I can’t verify that number because the Xbox Live Indie Game developer portal is dead. I do recall spending about $5000 USD on art assets for the game and not covering those costs.

Rock Bottom (2012)

The third game I created for the Xbox Live Indie Game store. I worked with a friend on this one, his job was to write the story and I would code the game. My friend wanted a 50/50 split of the profits, but I convinced him to take 20% instead.

This was a big mistake on my part. If you partner with someone and don’t give them an equal share they’re going to be demotivated and wont do very much work. That’s kind of what happened. If we went with a 50/50 split we could have met up everyday and worked on the game together.

Anyway the game came out terrible. There are videos of this game out there on YouTube. I believe it sold even worse than Let’s Get Fiscal, and cost even more money to make.

The Rise of Gaddafish (2012)

The fourth game I created for the Xbox Live Indie Game store. Personally I think it’s a better game than Rock Bottom, but it sold terribly. It turned out to be the worst selling Xbox game I made.

KILL THE CLEAN SHAVEN (2013)

This was an XNA game, inspired by Contra Hard Corps. The main character is called Rugged McBeard. He is part of a paramilitary organisation known as The Beards. Their one objective is to “KILL THE CLEAN SHAVEN”. Personally I think the name of the game is really cool.

During development I put up a few clips of the game on YouTube. I abandoned this game to make Girlfriend Plus. I should probably open source the assets and the code since I don’t plan to work on it anymore.

International Racing Experts (2013)

Also an XNA game. Following the success of Tokyo Hosto I planned to make another visual novel. It was a straightforward project because I already had the engine and the relationship with artists.

However I abandoned it to work on Girlfriend Plus.

Sim Kim (2015)

I hadn’t worked on a game for a few years, so I felt like making a visual novel. In 2014 I spent a year working at a game studio with the Unity game engine. It seemed like the logical choice for a game so I used Unity to create Sim Kim.

Sim Kim is a visual novel where you play as Kim Jong Un. You have to help him get through the problems he faces as the leader of North Korea.

You can play Sim Kim for free on itch.io

I just played it for a little bit, it’s not bad and more or less finished.

Cleared for Takeoff (2017)

I got a job offer from Credit Suisse in August 2017, but the job didn’t start until October 2017. So I had two months of free time. I used those two months to work on a game where you play as an air traffic controller. The cool thing about this game was you had to talk to play this game, just like a real air traffic controller.

It’s kind of a cool idea, but I didn’t finish it. I also made this game in Untiy

Alexa Girlfriend Plus (2018)

When I was at Credit Suisse a guy called Sandeep asked me to give a five minute talk about something.

“What do you want me to talk about Sandeep?”

“Doesn’t matter.”

I decided to talk about how to make an app for Amazon Alexa. I went through a tutorial online, and then deployed it to AWS Lambda. Then I did a five minute talk about it.

I thought “Hey that’s pretty cool, I should make Girlfriend Plus for Amazon Alexa.” I took a character from Girlfriend Plus and hired a voice actor to record all the audio.

Players would start a conversation, and then choose how to reply using options. It might go something like this:

  1. Game: Hi [PLAYERNAME] how are you? Reply with A: Doing good or B: I am mad.
  2. Player: Reply with B
  3. Game: Oh no sorry to hear that.
  4. And so on.

Interestingly I deployed this Alexa App to AWS Lambda, which is a serverless system. I used Lambda because the guy in the tutorial used lambda and also because Amazon had some sort of sweet deal. It went something like:

“If you host your skill on Lambda, we’ll give you tons of AWS credits. Way more credits than you need to pay for Lambda. You can use those excess credits on other AWS stuff.”

Is that sweet deal still in effect? It is. Is my skill still running? It is! This is really cool, I deployed it in April 2018 and have not done anything since then. It’s still up and running.

Every month since I launched this skill I received between $50 and $100 USD in AWS credits. I could go through my AWS bills and total up all the credits I gained, but I don’t really feel like doing that. I’d say I got about:

$50 * 6 * 12

= $3600

Is this a failure? Maybe not, but I wouldn’t classify it as a success either.

Plelarious (2020)

I liked to think of Girlfriend Plus as a chat application simulator as well as a fake girlfriend app. I started thinking “What if I made an Instagram simulation game instead? Surely people would like that as well.”

Well I started making it, and I used an advanced programming technique known as Event Sourcing. Banks use event sourcing to calculate your bank balance. Instead of storing it as a number, they store all the credits and debits in your account. Then they sum them all up and tell you the balance.

There are benefits to using Event Sourcing but it complicated my design and made working on Plelarious hell for me. I still think Plelarious is a good idea, in fact now with generative AI it’s a mega excellent idea. If I was going to work on it again I’d like to partner up with an awesome UI developer.

Girlfriend Plus Web (2020)

I worked at a crypto exchange from February 2020 to November 2020. After I left I started working on Plelarious again. I realised it was too complicated, and I wanted to build a subset of the app. The idea was to use the Plelarious code base to make Girlfriend Plus for web browsers. This is what I was working on right before starting Bank Statement Converter.

The biggest problem with Girlfriend Plus Web is that you can’t really send notifications. One of the best things about Girlfriend Plus on iOS/Android is the notifications.

Another problem was, I was sick of working on this application. I started working on Girlfriend Plus in 2013, I had spent way too much time on it.

CantoRead (2021)

CantoRead is an iOS application that helps you to learn Cantonese vocabulary. I created it for myself. Often I would see unfamiliar Chinese text around Hong Kong and want to look up the characters.

CantoRead lets you take pictures, and then it uses OCR to recognise the Chinese text, then it looks up the characters and phrases in a dictionary. From there you can make flash cards.

It wasn’t a bad idea, but Pleco kind of lets you do all this apart from the OCR feature. Soon after launching CantoRead iOS added really high quality offline OCR. That kind of killed my motivation to work on CantoRead.

CantoRead did go live on iOS but very few people downloaded it. It’s still available but I recommend using Pleco instead.

Solana Chess (2021)

A friend came up with a blockchain game idea. The idea was something like “People stake money behind a chess move. The move with the highest amount of money behind it is executed by the game. If the side you stake money behind wins the chess game, you take a portion of the money staked by the losing side”.

The game we had in mind was chess, but I’ll use tic tac toe in the following example because it’s simpler.

Board #1 - X turn

[ ] [ ] [ ]

[ ] [ ] [ ]

[ ] [ ] [ ]

Board #2 - O turn

[ ] [ ] [ ]

[ ] [X] [ ]

[ ] [ ] [ ]

Board #3 - X turn

[O] [ ] [ ]

[ ] [X] [ ]

[ ] [ ] [ ]

Board #4 - O turn

[O] [ ] [ ]

[X] [X] [ ]

[ ] [ ] [ ]

Board #5 - X turn

[O] [O] [ ]

[X] [X] [ ]

[ ] [ ] [ ]

Board #6 - Game over

[O] [O] [ ]

[X] [X] [X]

[ ] [ ] [ ]

User #1

User #3

Example over, please stop thinking about the example. Theoretically it’s possible, but then a question arises. Why would anyone want to do this? To make money? If so, then surely you’d just use a chess playing AI to win this?

I figured that would happen, but I didn’t really care, I wanted to make it for the hell of it. Well we chose to code this in Rust for the Solana blockchain. Let me tell you, writing Rust is very difficult. You need a brain the size of the earth to do it. Writing code for the Solana blockchain is also mega difficult.

I could code this thing as a Web 2.0 app in about a week, but in Rust and Solana? No chance. The difficulty of the tech sucked the fun out of it and I gave up.

Solana Chess never went live.

Detective Benny (2021)

Another visual novel game I started working on. This one was written in JavaScript and used the Phaser game engine. I barely worked on this and failed to launch it.

NFT Watches (2021)

I talked about this a bit in the month by month chapters. This took up a lot of my time, and we failed to launch it before the NFT market collapsed. I don’t think I’ll do another project like this again. The main problem with it was I didn’t believe what we were selling was of value.

Project Management Sim (2022)

A game where you play as a project manager. Your job is to gather requirements from users, pass them to the developers and then verify what the developer made matches your ‘specification’.

My original idea for this game was to make a game where you’re a project manager, but the way to beat it is to do nothing. If you try antod interfere in any way you kill the project.

This game is 80% done, I should publish it on itch.io as is, maybe even open source it because I don’t think I’m going to finish it.

SocialMediaMonitor.io (2023)

I talked about this in the January 2023 chapter. Of all the failed projects, I think this one had really good potential. We operated it for less than two months, but we had quite a lot of users. If we kept working on it and talking to the users we would have figured out what to build.

This one failed because I was working with people who had full time jobs. You just move so much slower when you’re working in your free time.

Launched but didn’t make any sales.

AngusForm.com (2023)

This one failed because I automated processes that people didn’t really want automated. Another thing is the UI for AngusForm.com looks so untrustworthy.

I automated two Hong Kong Transport Department forms and one form for the Hong Kong Police. Then I bought ads on Reddit. People panned me in the comments for that Reddit Ad.

AngusForm.com is a useful website if it automates forms and processes that lots of people want to do. My new thinking with AngusForm is:

  1. Let people upload a form. PDF or series of image files.
  2. Let them define the fields they want filled in on that form.
  3. Generate a web form from the fields they defined in step two.
  4. Let the users share that web form

The difference here is I let the users choose what forms they want automated. I can even hire people to use AngusForm.com to create forms.

AngusForm will provide printing/mailing/payment collection services. I still think it’s a good idea and I think I will come back to it at some point.

Customer Support Sim (2023)

A game where you play as a customer support representative. I wrote this in Kotlin and Raylib. The game is playable, but not very fun. I mainly made this because I wanted to create a game in Raylib.

Successful Projects

Get Rich or Die Gaming (2010)

Around 2009, when I was at university I didn’t have much to do, so I spent a lot of time playing adventure games from the late 80s and early 90s. I especially liked the Leisure Suit Larry series. At the time adventure games were not cool anymore and developers had stopped making them. This made me sad so I thought “I’ll make my own adventure game!”.

Somehow I found out about a piece of software called Adventure Game Studio. It had everything I needed to make an adventure game. I started writing the story for a game I had called “Business Adventure” and did some coding with Adventure Game Studio.

But then I was offered a programming job. I took the job, and put “Business Adventure” to one side.

What a charming young man I was.

At the end of 2009 I found out about a game library called XNA. I watched a series of free tutorials on how to make a 2D game. The series was really cool because it went really slowly and the instructor did every step on camera. So I followed along, understood everything and thought “This doesn’t seem very hard”.

I had a ton of free time at work, so I started coding Business Adventure in C# and XNA. My reasoning was “If I use XNA I can sell it on the Xbox 360, that would be cool”.

A friend of mine convinced me to change the name from Business Adventure to Get Rich or Die Gaming. I used to work on the game, and then bring it into the office to show my colleagues. They would play it, tell me it sucked and laugh at me for how unintuitive the controls were.

I changed stuff based on their feedback. When I felt it was done I submitted it to the Xbox Live Indie Game Store for review. Around this time someone told me not to submit it. I think they were worried it would get bad reviews or people would tell me it sucked and I would get sad. That kind of thinking didn’t really make sense to me, the most fun part of making a game is seeing other people play it. It went on sale on October 14 2010.

I don’t have the raw sales data, but I do have this graph. It went on sale for 80 Microsoft Points, which equates to about $1 USD. In the first week it made about $7000 USD. Pretty exciting for a 22 year old. Since then I have released it on Windows Phone, Windows 8 Store, iOS, Android and Steam. I’ve permanently lost a lot of the sales data, so I can’t really say how much it made in total.


I think it has brought in roughly $100,000 USD over the last fifteen years.

Tokyo Hosto (2013)

My sixth and final game for the Xbox Live Indie Game store. I reckon it’s the best one I made. It’s a game where you play as a young guy starting out his career in a host club in Tokyo. In March 2013 I went to Tokyo with a friend. One day we went to some weird suburb and my friend took part in a Magic the Gathering tournament. He did really well so we were there all day.

I had nothing to do, so I sat at an empty table and wrote the story for Tokyo Hosto. I wrote the majority of it in the two weeks I was in Tokyo.

I had worked with an animation studio in Cebu, Philippines on two other games. I hired them again for this game. Since they were pretty close by I thought “Why not go for a holiday and meet the team”. It was a great trip, they were really nice and we spent a lot of time hanging out.

Here’s a picture of me and the head of the studio Philmore at Kawasan Falls. The animators did a great job, I think the game came out well but wasn’t a mega success. I lost the sales numbers, but I’d say the game made about $20,000 USD.

Girlfriend Plus (2014)

In 2013 I was paying for a hot desk at a co-working space in Hong Kong called Cocoon. Cocoon was more interested in incubating start up companies than selling office space. Because of this they offered free ‘business analysis’ meetings. Someone asked me if I wanted to take one so I said yes.

I talked with a woman called Joyce who I think was an executive at a diamond company. I told her about the games I had been making. She said “How do you know how well a game will sell when you’re making it?”

“I have no idea, you just make it and see”

“I see, well then I think you should try to increase the speed you make games. Now it takes you three months to make a game, but if you can get it down to one week you’ll be able to have more chances at success”

This was an interesting idea, and I wandered around thinking “How can I make a game in a week?”. The problem is I needed to get a lot of art assets made. Things like music, voice acting, animation, concept art, background art and writing.

Could I make ten games at once? Probably not, I didn’t have the money or the project management skill to do that. Around that time Tinder was a really popular app and I was thinking “Could this app be turned into a game? What about a game that’s basically a Tinder simulation?”

I was also checking out Android apps to see what apps people were downloading. Virtual girlfriend apps were very popular, they had mega download numbers. I played a few of them, and they were all terrible. I started thinking “If I make one of these, but good, people will download it”.

Then one day I got the idea, a Tinder simulation virtual girlfriend app. I knew exactly how I wanted it to be. Later that day I met up with two friends and we went jogging. I told them about my idea. They both told me it was an excellent idea. One of them was a guy called Hubert who is a programmer. He said “Angus I will help you make this”.

Hubert and I coding Girlfriend Plus at Cocoon

Hubert has an amazing work ethic. We would meet up at 8 AM in the morning, and work until 6 PM at night. Hubert would sit at the computer with perfect posture, smashing in excellent code in silence. At the time we both had zero Android development experience. I was amazed at how much quicker Hubert learnt Android development. I learnt through tutorials and videos, while Hubert read the official Android documentation. I found the official documentation very difficult to understand.

We started coding in October 2013. The original plan was to launch the app with ten virtual girlfriend chats. Which would require:

  1. Hiring ten models
  2. Writing ten scripts
  3. Hiring ten voice actors
  4. Coding the app

We started off by hiring writers to write out the script for a character. The script would include picture messages and audio messages. The writers would define what they wanted in a picture message. They might write something like “Leilani is at the gym, she is stretching while taking a mirror selfie”. The script would have about twenty picture messages.

Once the scripts were done we would hire voice actors to record the audio messages. We would also hire models, and ask them to take photos to match the picture messages descriptions in our scripts. This turned out to be a big ask. We hired a lot of models, but very few of them took the photos we needed. This was holding everything up, so we flipped the plan around.

Instead we hired models, and paid them for whatever photos they already had. Then we would pay writers to write a story around the photoset we had. This went a lot better.

Getting Lean

In early December I read The Lean Startup. I actually read about half of it, that’s the leanest way to read a book. The book made me realise the importance of launching quickly. Originally we planned to make ten characters and then launch the app.

The lean Startup made me realise we should launch with one character, and then add characters over time through app updates. Then we could react to what our users said about the app. I suggested this to Hubert and he was down with the plan.

I spent the rest of December writing Java, fighting Gradle and editing the content files.

Launching

We launched Girlfriend Plus on January 10th 2014. The version we launched had one character, and no payment processing code. People downloaded and played the app which was encouraging. About a week later we added a character players could pay $0.99 to unlock. On the first day a few people bought that character.

Revenue

Across various app stores, it has made over $300,000 USD.

Tech Stack

Programmers love debating about how to architect their applications. I like to use old and boring technology.

Amazon Lightsail

Amazon lightsail is a cheaper version of Amazon EC2. It has a lot less features, but I don’t really need any of those extra features. I get my virtual machines, static ip addresses and managed database instances from Amazon Lightsail.

Lightsail is cheaper than EC2, but it’s still kind of expensive. A friend of mine has suggested I save some money and rent bare metal servers on Hetzner instead. I’m thinking about it. I’ll get more performance per dollar, but I might have to colocate some stuff. One idea is to put the build server, and dev servers all on one bare metal server. That’ll save me some money.

Postgres

I used to use MySQL, but people seem to think Postgres is better so I tried it out for Bank Statement Converter. It seems fine, been pretty happy with it. I don’t use any of the cool features.

Kotlin

I learnt Kotlin when I worked at Credit Suisse. It’s a really nice language, and interoperates nicely with Java libraries. I wrote the backend in Kotlin.

Typescript

The front end is coded in Typescript. It’s nice to have types.

Ktor

Ktor is an HTTP framework, I chose it because someone recommended it to me. It has mostly been fine, although it can be very complicated. It is developed by JetBrains.

Stripe

I use Stripe for payment processing. I’ve been pretty happy with them.

Ansible

I use Ansible to set up new virtual machines, create builds and deploy builds. I much prefer it to Kubernetes and Docker. I don’t like using Kubernetes.

It all works, but runs a little bit slow.

Buildkite

I use the Buildkite to trigger builds and to deploy builds into dev or prod. At Credit Suisse we used to use TeamCity, it was fine, but expensive and very complicated. BuildKite is a lot simpler and a lot cheaper.

NextJS

I didn’t choose to use NextJS, it was something Dom chose. I think it’s okay though. I knew how to make UIs using React, so learning NextJS was easy. It performs pretty well, the page load times are fast. When the NextJS builds fail I have a hell of a time debugging them.

Netlify

I’ve liked Netlify for the most part. Recently a few horror stories around bandwidth have freaked me out. I am considering moving some of my static websites over to Cloudflare.

Brevo

I use these guys to send transactional emails. Brevo’s sign up process is a lot simpler than SendGrid’s. Their free tier is very generous as well, I’ve only just moved off their free tier.

My Working Style

TODO.md

In the root of whatever project I’m working on I have a text file named TODO.md. This is what I use instead of issue tracking software like Jira or Trello. Everytime I think of something to do I put it in the backlog section.

When I start working I grab some items from the backlog and I put them into the section under today’s date. When they’re done I put an x in them. I use the items as commit messages as well. This means I don’t need to think about commit messages. 

I don’t know if this would work for people working in teams but it works for me. The benefit is I don’t open a web browser to mark something as done. This helps me stay in the programming zone. Once I open a web browser it can be really tempting to check out what’s going on on Twitter, Instagram or some other website.

Streaming

For other apps I’ve worked on I would stream myself coding on Twitch. This helped me focus a lot. When you’re live streaming your screen, you aren’t going to waste time on the internet.

I didn’t do this when developing Bank Statement Converter. A lot of the work I do  is improving results for specific bank statements. This requires me to open up the bank statements. It’s personal information and I cannot live stream it.

Going to the office

In theory I don’t need an office. I don’t meet clients, and I don’t have any employees. However I still rent a hot desk at a coworking space. I don’t like spending too much time at home. It makes me go a little bit crazy. It’s also nice to separate work time from relaxing time.

I do work from home quite a lot, but I use my office as much as possible. This helps me, but I know a lot of people who work much better at home.

Trunk Based Development

I use Git, but I do not use branches. Partly because I’m the only one coding the app, but also because I’m a fan of Trunk Based Development. When I worked at Credit Suisse we used SVN and we committed everything to one branch.

It went really well. We didn’t fight over Pull Requests, we didn’t have merging pains. We also did a lot of pair programming. I believe that pair programming eliminates the need for pull requests.

Automated Deployment

I use BuildKite to automatically test and build the app every time I commit. If the tests pass the code automatically gets deployed to dev. At any time I can specify a build number and manually trigger a deployment into prod.

Copycats

I publish live sales data on Indie Hackers. This has led to a lot of people writing articles about Bank Statement Converter. It has also led to a lot of copycats. Sometimes these guys email me asking about technical implementation details.

I don’t really like the copycats, but I do understand they’re allowed to copy me.

If you’re thinking about copying me, I suggest instead you send me an email, I can give you some of my cool app ideas. Maybe we can work on them together on one or you can just have the idea and go nuts.

me@anguscheng.com

Data

Date

Users

Revenue HKD

MRR HKD

Ads HKD

April 2021

3

$0.00

$0.00

$1,110.00

May 2021

75

$791.00

$0.00

$5,700.00

June 2021

151

$1,246.00

$0.00

$8,150.00

July 2021

145

$2,397.00

$569.00

$10,800.00

August 2021

159

$1,829.00

$984.00

$10,200.00

September 2021

116

$2,057.00

$1,607.00

$2,760.00

October 2021

48

$3,681.00

$2,422.00

$0.00

November 2021

104

$5,231.00

$3,282.00

$0.00

December 2021

112

$7,490.00

$4,612.00

$0.00

January 2022

178

$10,050.00

$6,974.00

$0.00

February 2022

178

$11,926.00

$9,040.00

$0.00

March 2022

209

$11,671.00

$11,049.00

$0.00

April 2022

215

$19,058.00

$13,184.00

$0.00

May 2022

181

$21,008.00

$15,792.00

$0.00

June 2022

234

$19,389.00

$16,811.00

$0.00

July 2022

357

$19,837.00

$18,139.00

$0.00

August 2022

328

$62,596.00

$21,701.00

$0.00

September 2022

448

$46,736.00

$37,521.00

$0.00

October 2022

341

$46,846.00

$40,730.00

$0.00

November 2022

392

$56,932.00

$43,914.00

$0.00

December 2022

356

$58,004.00

$48,959.00

$0.00

January 2023

442

$66,873.00

$50,408.00

$0.00

February 2023

506

$62,457.00

$57,820.00

$0.00

March 2023

602

$66,839.00

$63,053.00

$0.00

April 2023

559

$96,842.00

$72,489.00

$0.00

May 2023

553

$86,179.00

$74,452.00

$0.00

June 2023

748

$81,921.00

$74,294.00

$0.00

July 2023

1299

$75,793.00

$76,392.00

$0.00

August 2023

933

$97,944.00

$83,218.00

$0.00

September 2023

1117

$109,219.00

$91,448.00

$0.00

October 2023

956

$128,150.00

$98,979.00

$0.00

November 2023

884

$142,569.00

$107,747.00

$0.00

December 2023

997

$130,019.00

$109,979.00

$0.00

January 2024

1373

$134,701.00

$126,130.00

$0.00

February 2024

1361

$161,333.00

$142,338.00

$0.00