How I built my first Chrome Extension, AstroBook, in less than a day.

I was toying with the idea of building Chrome Extension for a while now. Everyone these days is so obsessed with building mobile apps, and the web is left overlooked, along with a long tail of great opportunities there. Such as browser extensions.

What’s cool about browser extensions?

  • Low churn — user installs an extension and, unless it’s a particularly annoying one, he or she is quite unlikely to uninstall it.
  • Top of the mind — Is your site or app is having a hard time keeping mindshare of your target user’s audience? Do users forget to go back to your site when they experience the problem that you are solving? — Why not leverage sites that billions of people go everyday to, e.g. Facebook, Google, Twitter, etc. An extension, once installed, can simply augment Facebook’s features and display it’s UI components right within Facebook’s or Google’s UI. Super cool!

Idea 💫

Okay, so what is our extension going to do? In my spare time, I’m interested in a variety of psychology frameworks, that try to describe compatibility between individuals. Such as MBTI, OCEAN, and … Zodiac signs! (I take all there things with a grain of salt, of course, and so should you. Sometimes they describe people well and sometimes not.)

And that’s what we’ll be building today — a zodiac compatibility extension, that checks how compatible you are with your Facebook friends.

Currently, when I want to check how compatible I am with someone’s sign, I go to their Facebook → copy their birthday → paste it into Google to find their sign → start another Google search request for e.g. “aries sagittarius compatibility” → click on the result and read.

Way too many steps! 😱 Wasting 15 minutes of my life each time. Let’s automate this madness!

Naming

I typically spend days trying to come up with a good name for any idea I have. I think I should spend way less. Or, at least for the very first version of the product. For this project, I decided that 💫 AstroBook would be a good choice. Astrology+Facebook=AstroBook. Fortunately domain name was available too: astrobook.co

Vision

Here is what I had I mind. Take any profile page on Facebook and add Zodiac Sign right under birthday info. That would already solve quite a bit of copy-pasting and Googling. Like this:

Next step, show our compatibility:

Bam! Simple, fast, easy, elegant.

Let’s write some code, finally

Basically there are 5 main files you need to have: manifest.json index.html app.js app.css and icon.png . They can be named differently, of course, but not manifest.json Manifest is the main file that’ll describe your extension. It contains it’s name, description, version, lists browser permissions your extension needs, and sites it should be working with. AstroBook’s manifest.json looks something like this:

{
"manifest_version": 2,
"name": "AstroBook",
"description": "Are you compatible with your Facebook Friends?",
"version": "1.2.1",
"icons": { "128": "icon.png" },
"content_scripts": [
{
"matches": [
"*://astrobook.co/*",
"*://*.facebook.com/*",
"*://twitter.com/*",
"*://*.twitter.com/*"
],
"js": ["jquery.min.js", "app.js"],
"css": ["app.css"]
}
],
"permissions": [
"tabs", "http://*/", "https://*/", "storage"
],
"web_accessible_resources": [
"matches.json"
]
}

icon.png is required. All extensions must have one. It’ll show up in browser’s dashboard. Here is our icon: 💫 Yay!

For this simple project I thought I should avoid all the fancy React.js wizardry and get by with vanilla JavaScript and some jQuery spaghetti code. I wont go much into detail about every single line of code I wrote (Feels like documenting my codebase, which I hate to do. Good code is self documenting), but I’ll just stress on a few tricky parts I’ve spent the most time on. So, the trickiest part was to identify when user’s birthday information is displayed on the screen, parse it and append my widget. This all boiled down to trial and error process with jQuery selectors and quite a bit of Facebook’s DOM analysis with DOM Inspector. At the core of the solution is a interval loop, that checks for url changes and is looking for span:contains("Birthday")

setInterval(function () {
if (currentURL !== encodeURIComponent(location.href)) {
currentURL = encodeURIComponent(location.href)
setTimeout(function () {
var birthdayDayCell = $('span:contains("Birthday")')
if ($('.astrobook').length > 0) {
return console.warn('AstroBook is already initialized.')
}
if (birthdayDayCell.length === 0) { return }
if (birthdayDayCell.length > 1) {
bDayCell = $(bDayCell[1])
}
initWidget(birthdayDayCell.parent().parent()) // Magic!
}, 1000)
}
}, 500)

initWidget($el) goes on and does all the job of parsing date from $el finding which Zodiac sign it is, and then append a widget adjacent to the element.

Local development process is fairly “okay”. You just have to load your extension’s directory into Chrome and then keep hitting “Reload” link all the time.
No hot reload 😥 available.

Okay, let’s see what we’ve got here. Opening Facebook, friend’s profile page:

Submission Process

First thing that comes to mind when hearing about “App Submission” is Apple’s rigorous, week-long review scrutiny. Fortunately Google’s Chrome Extension submission process was anything but that. It was a breeze. Google takes $5, a one time fee, to ensure you have serious intentions on the app store. After uploading .zip file with your code, it takes about an hour or less for extension to make it to the store, where it’ll get a lovely page like this.

Here are some screens from Chrome’s Web Store admin panel:

Interesting nuance. Each extension should be linked to a domain name. I wanted to do as little work as possible and registering domain, creating a landing page, was not part of my initial plan. Oh well, what needs to be done must be done. Finishing off the day around 11pm, I thought I’d postpone this for tomorrow.

Day 2

Ironically, building a landing page took more time than building the extension itself. I won’t go too much into details here, as web dev / html / css topics are in a vast abundance on the Internets. One thing worth mentioning is that I spent some time selecting where to host my landing page. I don’t like WordPress; hosting static files on AWS S3 (like I typically do) is not ideal for SEO hence I wanted to avoid that; I love Heroku’s push-to-deploy experience, yet I did not want to pay for their dynos. After eliminating a few other options, I settled on Amazon’s new service Lightsail.

Best way to describe this new service, is to compare it with DigitalOcean. Think of AWS Lightsail as “DigitalOcean in orange colours”. It is identical. Same value prop, same pricing, same simplicity.
(Sorry, DigitalOcean 😢 I hope this won’t put you out of business just yet.)
A spawned an instance for $10/month, installed Dokku and pushed a fresh Sails.js project. Smooth sailing!

Again, I wanted to get through this as fast as possible and did not want to overthink the landing page. Hence I shamelessly stole landing page looks from Grammarly:

Nice! By the way, this gradient was inspired by WebGradient.

Day 3

This day was set aside to blog. I rarely blog, but recently decided to document my work process, be open and hopefully bring some value to you.


Summary

I really enjoyed working with such time constrains. Sort of “one-week-startup”. Pick a project that you can code up in a day or two, write blog post, submit on product hunt and forget about it (unless it takes off, of course). I’m definitely looking forward to repeating this again. Low time commitment, low expectations — pleasing sense of completion.

Let me know what you think! Tweet me at @ksaitor. Like and share. 😊 Know someone who’d use AstroBook? Send it to them. Be a good friend.

Like what you read? Give Raman Shalupau a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.