Journal entry – May 28, 2020

I keep a personal journal sporadically. Last year I dropped off from ~March 2020 and picked it back up on May 28, 2020. It was the period that coronavirus was the worst it got in Sydney* (*Simpsons ref: worst it got in Sydney, so far.)

Every day I review the entry from a week ago, a month ago, and a year ago. I’m not 100% with journalling so pretty often there’s missing entries, but this one is my favourite so far. It’s from a year ago today.

I keep the journalling private to only myself. It’d be good to share somehow one day with my family/kids, but there’s already so much content that I guess it’d need a thorough review first.

It’s a point in time and only lightly edited. I remember the period very vividly and also it seems like forever ago. One day, I hope this post gets lost in a sea of hundreds of my daily posts (there’s currently 80).


Started at Thu May 28 13:20:51 UTC 2020


It’s been so long. I’m here just to try to start the habit.


In the meantime, Coronavirus hit, and Australia did really well. We as a family also did really well.


In USA, 100,000 people have died as at yesterday. 100 people here. All the countries in the world are handling it differently. My USA friends are a little bit pretty conservative so it’s interesting seeing it through their eyes (‘the people who are dying were going to die’, etc).


The kids had 2 weeks of home school and then school holidays. Then another 2 weeks of full home school, and then basically back full time. Krystal loved it. We all got a bit closer (e.g. we had lunch together every day, which was fantastic!). All the kids handled it differently though. Austin grew up very quickly having everyone around. Emmett didn’t miss real life at all. Hudson just wasn’t himself. A bit moody, a bit withdrawn. He thought he probably needed to see his friends and we thought so too.


We did a good job of isolating ourselves. I went out for a takeaway coffee most days and that was it. A few times we went out for takeaway and ate it in the car — the Kebab Van in the Mitre 10 carpark, or McDonalds in the shopping centre carpark. Restrictions are lifting slowly now. 10 people are allowed in restaurants and cafes. NRL started again tonight.


We didn’t see Rod & Bronwyn for the whole time. The family all stayed away. We finally got to have a catch up and had the nicest night. Tom and I pulled an old couch out to the fire and we chilled on it with Krystal.


Scarlett had her 4th birthday under the lockdown. Her friends from dancing decorated their cars and came for a drive down our street. It was at the absolute height of the lockdown. The neighbours all watched from their windows. The mums passed Scarlett’s presents out the windows and basically yelled out the windows in conversation. The whole thing probably lasted 15 minutes and then they were gone. It was so amazing, one of those things that won’t ever happen again.


The neighbours house caught fire last week. Krystal ran down and told me, and we ran out and helped with the efforts. I really do think we stopped the place from fully burning down, once I saw the photos. Poor buggers.. We don’t see much of them, but the more we have seen them over the xmas fires and stuff the more they seem alright.

Spatie QueryBuilder/Eloquent – filter based on child attribute

One of those ‘all the time’ patterns I can never quite remember that is hard to google for.

The piece of code:

QueryBuilder::for(Entity::class)->whereHas('entityType', function($q) {
            $q->where("entity_types.is_task", true);

Explanation:

QueryBuilder::for(<Parent Class>)->whereHas('<relationship name of child/relative>', function($q) {
            $q->where("<table name>.is_task", true);

In this case, the child/relative is defined like this:

    public function entityType()
    {
        return $this->belongsTo(EntityType::class);
    }

Copying small startups, test #1

It’s all going to take a while to work out.

I’ve got an old online campsite booking tool that I charge the original customer $1k/year to keep switched on. It looks, feels and quacks like a SaaS, so will be useful to get some re-exposure to a lot of the side pieces to running the micro-SaaS.

Things like:

  • Applied formula SEO
  • Support as Marketing
  • Awful youtube how-tos as Marketing
  • Science of screenshots / pricing / features / waiting list
  • Analytics
  • Getting a marketing site template sorted
  • Forgotten steps like buying a domain

There’s no dev required to do any of these on this particular product, so it’s now Copying Small Startup Test #0. Revenue goal is $0. They’re all pretty light tasks in and of themselves, and might take me a month of 1 hour a night to knock a few off.

There’s no startup being copied here, but I assume there’s 10 others out there that I can be inspired by later.

Swagger to Laravel Library

Given an OpenAPI API endpoint, if you can export the OpenAPI JSON specification, it can easily be turned into a client library for use in laravel.

Download the swagger.json file to the current folder.

Run:

docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli generate -i "/local/swagger.json" -g php -o /local/out/php

Under the ./out/ folder is now a client library to work against the API.

I made use of this post when working through:

Firebase – searching where string starts with

Firebase doesn’t have a nice way to say .where(searchField, ‘startsWith’, searchTerm)

The easiest way is to search for text strings that are greater than the search term, and smaller than the next string after the search term.

E.g. when searching for rows that start with “Rhys”, we really want everything greater or equal than Rhys, and everything less than or equal to RhysZ (to oversimplify).

Here’s a quick and easy way to do that, using \uF8FF (a high unicode code point) as the trailing character.

 return usersCollection
  .limit(perPage)
  .where('email', '>=', searchText)
  .where('email', '<=', searchText + '\uF8FF')
  .get()

Properly adding v-model support to a component (vue.js)

This is one of those things I always forget that’s hard to google properly.

In a child component, adding v-model support starts with a ‘value’ prop. This is the input value arriving at the child component. In the example below, I’m expecting to work with an array.

  props: {
    value: {
      default: () => [],
      type: Array,
    },
  },

We don’t want to mutate the underlying passed in value when it gets changed in the component, so the value prop is cloned into a data property.

  data() {
    return {
      editingRow: false,
      sections: [...this.value]
    }
  },

From here on in, we manipulate only the sections data, never touching the input value prop.

 saveSection(){
      this.sections.push(this.editingRow);
      this.editingRow = false;
}

When it’s time to notify the parent and sync the changes (on clicking save, or just on a practical point within the app), we emit a ‘input’ event with the new contents of the value.

this.$emit('input', this.sections);

Copying Small startups – Food Booking Software.

Food Booking Software – mind map.

Eating at a pub involves lining up with the other patrons, reviewing the menu, speaking back the order and any alterations to staff who enter it in the system and ring up a price.

The customer pays for the order and the order goes to the back-restaurant/make-bench to be made.

A modern approach (ME&U app?) allows the pub to create a restaurant in the app and add their menu items, sorted by categories. Products have a price (alternatively a second price for other purposes, e.g. members). Products have extensive alterations.

The pub prints labels for each desk that have the site code and table code embedded in a QR code for the customer to scan. The business can alternatively print nice labels and have them sent out – the labels attach to a cutlery basket, stick to the table, The customer gets taken to the app with a querystring that can load up the restaurant and the menu.

The customer fills a ‘cart’ on the site and ultimately checks out. The customer needs to make payment when they submit an order. The restaurant can begin cooking the order for the customer, via a POS integration.

If the customer does not understand, gets stuck, or chooses not to use the app, they can still proceed ‘the old way’.

The customer can continue to shop on their app for drinks and order and pay online.

The customer can use the receipt link SMS’ed to their phone for disputes etc.

If payment is through the app, a clip will be paid to “Ordering app”.

The ‘pub’ needs customised labels for tables and an easy way to re-order or re-create their own. All QR codes should be easily reproducible.

The orders only make it to the back kitchen by a POS integration or a receipt printer on site.

The pub has a dashboard they can use, but this is not a key part of their use of the platform (e.g. they don’t need to get orders out of it, etc). They might sign in for refunds and billing enquiries, check payment settlements, update menus (if not POS integrated).

The obvious first step is to get in touch with a restaurant manager or owner and run the idea by them – does it sound like it’ll work?

Unoriginal Side Project Examples

No more original side projects.

This is an ongoing article of unoriginal side project ideas that could be executed. I don’t know what I’m doing, I’m just documenting this so I can find it again later.

The unoriginal side projects will follow a bit of a formula – having many elements in common. I’ll keep revisiting the article and adding examples.

Certain SaaS products go “Enterprise” or upmarket and leave a hole that can be filled to deal with smaller customers. They end up full of thousands of features, and there may be an underserved market of users who could be paying for a much lighter product.

They end up as “Request a demo” or “get more information”.

“Ha, twitter!? I could write that in a weekend!”

On reflecting on the enterprise behemoths below it looks like I’m doing the old “Ha, twitter!? I could write that in a weekend!”. It’s not that. I want to take an enterprise behemoth, slicing it back down to what it used to be, and build that.

Any one will still take me months of nights, realistically. I’ve got a full time job and a big family that both take priority, but also a strong desire to stop trading hours for money.
I’ll build up a stack I can re-use, find some valid and invalid assumptions, ship some products, and keep moving the goalposts as it goes.

Who’s going to buy the stripped out tools?

The target market for any of these projects will be a person with an online or offline business who already knows they need a <SaaS for X> (where X is “Trust widget”, “Support ticket tool”, …).
I don’t want to convince them they need one – I suck at that. I just need to convince them that this will also generate support tickets, doing much the same shit as Zendesk. They’re not going to find me in position 1 on google – that’ll always be Uservoice. They’re going to find me on page 2 of google (after abandoning all the “Schedule a demo!” shit), read a few articles, watch a video and create an account on the spot. Sometimes, hopefully.

Follows is my incomplete list of up-market enterprise SAML HIPAA compliant “schedule a call with our executive integration team” bullshit unicorns that I think have an underserved lower end of the market.

Ideally, I’d pad this list out with some smaller stuff, but hey, I’m starting here.

Help Desk Software

Customers email [email protected] and start a conversation thread with one or multiple support agents.

Customers use live chat

A knowledgebase is slowly created, which becomes SEO long tail bait, reference material, internal bible, and inbound lead generation.

Zendesk $5/agent/mo to $19/agent/mo (Max $99/agent/mo).

HelpScout $20/agent/mo to $35/agent/mo

Feature Request Software

Customers visit a feature request leaderboard, and it helps drive feature development of the SaaS.

In theory helps drive development roadmap. Gives users a place to help each other, self diagnose, request features.

uservoice is the big one ($499+/mo.). Loop, roadmap.space, etc are others.

Forms Software

Users can fill out a form, and the data is shipped to the form owner or a google sheet.

The form has many field types, including payments, maps, etc. New field types can be added regularly.

Paperform (12.50/mo to 32.50/mo, up to 82.50/mo)

Spreadsheet Software

Users fill data into spreadsheets, either with forms or spreadsheet view. They can link the sheets together, export to CSV, use as REST API.

Airtable $10-$20/user/mo. Airtable is a $X00B company, but 99% of the usefulness (that I can see) is linked spreadsheet rows that you can share with co-workers and devs.

Trust and Reviews

When an order is shipped, the trust server sends an email to the customer in a few days asking them to review the products and review the website.

The customer can review both and the data flows both to the website and to a list of the products.

Trustpilot $189/mo

Loyalty and Rewards

Award points and credits for purchases to a customers account. Customer can spend the points and credits on checkout.

loyaltylion: $159/mo