Dan Ryland

How Supabase Cron helps me stay motivated, build discipline and find encouragement

I wish this wasn’t true but:

Motivation is fleeting.

It comes and goes.

Urh.

Homer from The Simpsons climbing a mountain

So what’s more valuable than fleeting motivation?

Discipline.

Discipline is far more reliable.

But if discipline is considered a skill (because it can be learnt) how can one learn and develop that skill?

Answer: by persisting

But it’s difficult to persist at something (especially when it gets tough) without the occasional word of encouragement, right?

Well, at least this is true for me.

*Drumroll *

Presenting the “Encouragement Coach!” (Trademark pending)

As part of Supabase’s recent Launch Week, they released Supabase Cron

Supabase Cron allows you to trigger a defined task on a specific schedule.

The task can be an SQL snippet, database function, HTTP request or a Supabase Edge Function.

What better way to try this new feature than to blend it with my Encouragement Coach?

OK, maybe that name’s a little long.

I’ll come up with a snappy character name for it in a sec.

Actually, even better.

Let’s do some Stan Lee alliteration:

‘Motivating Max’

‘Encouraging Ellie’

‘Cheerful Chase’

I like the Mad Max, steam punk, desert discipline, so let’s go with that.

Motivating Max will send Telegram messages a few times a day with custom messages of encouragement.

Thanks to MidJourney, I have my avatar:

Motivating Max generated by MidJourney

Now let’s place this contextually within Insidr.

Insidr is a direct-to-fan monetisation platform for artists to earn more from their music.

Artists share unreleased music, videos, and photos exclusively with fans.

It’s a place for artists to build their dedicated fanbase while still owning their own audience data.

Thinking of Insidr, there’s lots of data-backed encouragements that come to mind:

  • How many artists signed up today
  • How many fans subscribed to artists
  • How many new songs have been uploaded
  • How many songs have been submitted for sync
  • Total number of artists
  • Total number of users (both fans and artists)

I remember hearing Ryan Serhant, American real estate broker, say that marketing is like building a sandcastle.

The tide comes in every day and wipes away your sandcastle forcing you to rebuild everyday.

The act of rebuilding is like doing marketing activities.

You want to do something everyday so that people remember you: your business, service or product (eg your sandcastle).

Sponge Bob building a sandcastle

With this in mind, the one metric I’ve been focused on is drawing more artists to the platform.

So, as encouragement for myself, I think it’d be cool to know how many signed up yesterday, today, in the last 7 days, this month and in total.

Blending this with GPT-4o for the encouraging content variations and we have ourselves a pretty good starting point.

Let’s get to work building it!

First, let’s build a Postgres function to get total number of artists yesterday, today, last 7 days, this month and all-time.

I’ll use the created_at field in my artists table to help with the counting.

CREATE OR REPLACE FUNCTION get_artist_stats()
RETURNS TABLE (
    today INTEGER,
    yesterday INTEGER,
    last_7_days INTEGER,
    this_month INTEGER,
    all_time INTEGER
) AS $$
BEGIN
    RETURN QUERY
    SELECT
        COUNT(CASE WHEN DATE(created_at) = CURRENT_DATE THEN 1 END) AS today,
        COUNT(CASE WHEN DATE(created_at) = CURRENT_DATE - INTERVAL '1 day' THEN 1 END) AS yesterday,
        COUNT(CASE WHEN created_at >= CURRENT_DATE - INTERVAL '7 days' THEN 1 END) AS last_7_days,
        COUNT(CASE WHEN EXTRACT(YEAR FROM created_at) = EXTRACT(YEAR FROM CURRENT_DATE)
                   AND EXTRACT(MONTH FROM created_at) = EXTRACT(MONTH FROM CURRENT_DATE) THEN 1 END) AS this_month,
        COUNT(*) AS all_time
    FROM
        artists;
END;

This can then be tested by running the following in the SQL Editor:

SELECT * FROM get_artist_stats()

Now for the second part: build the Supabse Edge Function we’ll be triggering within the Cron.

I’ve created a new edge function with the following command:

supabase functions new motivate

The edge function will call our get_artist_stats function and use the response in a beautifully created GPT-4o prompt.

This will also mean I’ll pass a period into the Edge Function so I can tweak the prompt for each given time it gets triggered.

I’ll have three crons for different times of the day: 8am, 12noon and 6pm.

After some tweaking, here’s the final prompt:

Knowing that it's ${periodMessages[period]}, generate a super short, bold,
and encouraging message in the style of Mad Max based on the following data
from Insidr Artists: ${JSON.stringify(data)}. Always include the number
prominently and focus only on one specific metric from the provided data.
Keep the tone fiery and empowering. Directly reference 'Dan' the founder of
Insidr too. Don't include hashtags. Don't write all in caps.

Once I have the response from GPT-4o, I then use Telegram’s API to send it via my Telegram Bot to myself.

To create the Telegram Bot, I need to speak to the @BotFather

BotFather setup

Creating the bot gives me a token to use in the API call.

A quick test of the Telegram API through Postman shows IT LIVES!

I then added the Telegram API call into the edge function and deployed.

Now for the final part, setting up each cron.

Supabase Cron setup

Two things that are nice about the cron feature:

  • Ability to use natural language to define the schedule (eg every day at 9am becomes the correct syntax: 09***)

  • Selecting the edge function is super easy. I just select it from the dropdown.

I also passed { "period": "morning" } in the HTTP Request Body field.

It was super quick to get three crons up and running.

Supabse Crons

For testing, I set each cron to run every 30 seconds. This meant I didn’t have to wait for 9am or 12noon for it to be triggered dynamically.

It looks great.

alt text

…but it’s missing something.

You know what will make these messages more encouraging?

GIFs!

Let’s grab some GIFs, randomly select one and change the Telegram API call from sendMessage to sendAnimation.

Here I moved the inital text property to caption.

alt text

Beautiful.

I’m super pumped now.

With all the crons set up, I went to sleep.

Morning came with the exact encouragment I needed:

alt text

Time to build another sandcastle!

Music artist? Get started with Insidr

Follow me on X/Twitter

Check out my Github