How I made “A new header photo daily.”

Recently I launched a tool which lets you change your Twitter header photo daily to a new one from Unsplash. Here’s how I made it.

Why I made it

The reason is very simple: I wanted to use it. For the longest time my Twitter header was just the color black. Sometimes I would go to Unsplash, download a photo, upload it only to change or remove it in a couple of days.

How I made it

Surprising it was actually extremely easy to build because of tooling. I used Laravel as my backend framework which made it super simple to handle things like OAuth, queues and scheduled tasks.

Twitter Integration

Laravel offers a package called Socialite which handles all the boilerplate OAuth for you. After about 10 lines of code I had full Twitter integration ready to go.

Schedule Tasks

This is one of my favorite features of Laravel. A scheduled task is obviously the work of a cron job. But in my experience cron jobs always get messy, you always have to Google around just to remember the actual order of the *. Not only that but the cron job is not part of your code base. You have to manually go in and change the crontab when you deploy your code.

Laravel has a nice solution for this. You basically go to their documentation, copy one cron job, paste it into your crontab and you’re done. Then you can fluently define when you want a certain commands to run, right inside your code.

In my case, I created a Laravel console command named schedule. All it did was look through all active users, and if the scheduled date of the user’s next header photo has passed I dispatched a job onto the queue to process and change that header photo. This is all it took:


I knew I needed a queue since the process of hitting the Unsplash API, grabbing a curated photo, and then uploading it to Twitter was a long task. Not only that but there are so many things that can go wrong (revoked user tokens, rate limits etc.). Isolating each of those uploads makes it easier to deal with when something does go wrong.

I’m not sure if my way is the best way or a even good way, but it works and has been working so I’m happy with it.

I created one job, named ChangeHeaderPhoto and all this job did was exactly that. The scheduler would dispatch this job onto the queue when needed.

The one wonky thing I did, is when something goes wrong.

If I hit Twitter’s API rate limit the job doesn’t fail but instead queues up another copy of itself with a 15 minute delay. Twitter’s API rate limit refreshes every 15 minutes, so theoretically next time the queue processes the job it should successfully complete it. And if it doesn’t because the queue is just absolutely full, well it’ll just keep pushing it back 15 minutes until it can process it.

In terms of handling other errors such as if the user revokes the application’s access on Twitter: the job would just silently fail and and mark the user disabled so it’ll never schedule the job again until they reauthenticate.

To make sure that the queue worker is always on and working, I used supervisor. I wouldn’t recommend reading their docs but rather reading Laravel’s documentation on it or this DigitalOcean tutorial I used.

Not much more to say about queues, but if you want to learn more on how to use it in your Laravel project read their documentation.

Other cool things I did

Time of day

So the one thing I spent a lot of time thinking about and deciding is what “every day” means for every user. What I mean by that is what time in that users day should their header photo be changed?

I think the easiest approach to this would be to schedule the user’s next header photo 24 hours from the time they sign up and so on. But what if they sign up at 3pm? It would feel disruptive and weird to have one’s header change in the middle of their day.

So what I did instead is I took every user’s timezone from their Twitter, and calculated the offset so there header would be updated around 5am-6am in their timezone ⏰. Why 5am-6am? Well that’s the time I feel most people are either: going to sleep, already asleep, or just waking up. That way the majority of users would go to sleep with one header, and wake up with another.

This creates a unique experience, and gives you something to look forward to: “What header photo did I get today?”.

Giving credit

So this wasn’t something I included at launch but instead a day after: giving credit to your current headers author. I admit I should've done this right away.

Sometimes you’ll really like your header that day and maybe you’ll want to use the photo as your background or lock screen. Giving credit to the author means I can give you options to explore more photos from that user, or download the original to use wherever you want.

It gives you the option to discover new photos which is not something I intended originally but it happened and that’s freakin awesome.

All of it

I want to just quickly list all the tools/services I used since it might be of interest to some people.

  • I’m a loyal customer of DigitalOcean, where the service is hosted.
  • Laravel as the backend framework.
  • Unsplash for the beautiful header photos
  • Bulma as the CSS framework.
  • Fries from McDonalds (seriously though).

Thanks for reading, you can follow me on Twitter here.

web dev

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store