Have you tried IFTTT?

Did you know they have a pretty kickass API called the maker channel?

For monashjobs, we wired up the API with facebook and twitter so whenever someone posts a job listing, it automatically created a new facebook post and tweet based on the job posting.

Now how awesome is that!

I participated in Unihack 2015 and made this.

We are still expanding upon it but the basic idea is to make every image on the internet taggable, a bit like how facebook does it

Currently it only supports images hosted on imgur but we are going to make changes to it(once I get some time heh)

Just looking back on how much PHP sucks and how badly designed cakephp is(the whole damn project, really)

At my university campus there are loads of free food events happening around. Unfortunately, I tend to miss most of them because of my lecture’s timings.

I always wondered how many are happening in a particular day because there are so many groups and societies who organize them. Unfortunately there is no central location where these events are posted.

So over the last week I created a nodejs app which collects the last 20 posts of these groups and pages using the facebook api and searches for keywords like ‘free’, ‘bbq’, ‘pizza’, ‘beer’, etc.

Here’s the tech behind it.

The architecture is a bit different behind this compared to my other side projects. The frontend is a pure html page on bitballoon and it gets the data via a rest api exposed by my nodejs server hosted on openshift.

First, it gets the posts and scans them for relevant keywords. Then it assigns a score of 0.5 to every keyword. Keywords like ‘free’ get a score of 1.

Then all the scores are added up and a a decreasing function is used. So 0.5 + 0.5 + 0.5 is not 1.5 but rather 1.0022

This is to combat keyword stuffing. It works surprisingly well too. The average score almost flatlines at about 1.6

Then I filter out posts who’s score is below 1. Then finally, I run another function to extract the time and location from the text and then all that data is saved in the mongodb database.

Turns out, there is a lot of room for improvement.

Strike 1

The first implementation was not bad. It did work but in the process, it caught a lot of unwanted junk.

The best analogy I can give is that of a fishing ship which catches sardines but also catches a lot of other non-edible fishes. Only problem being that sardines constitute less than 50% of the catch.

Take an example of this sample post:

There is FREE ENTRY for any University student to the Blue Diamond Stakes today.
Pre-drinks start at the Racecourse Hotel at 11:30 where you can drown all of your post-Beach Day blues..

It matched ‘free’ and ‘drinks’. Bam, strike #1

Strike 2

There was clearly a need to refine the algorithm. The scoring system needed a revamp.

So we have two scores. One is the score we get from the parser and the other one is the compare score which is a constant(1)

So : score > compare score (Which means the post is about free food)

I realized the compare score needs to be refined. Having a static value of 1 or even 1.5 doesn’t change anything. Using our previous analogy, it just makes our net smaller or larger. We need to refine our net.

This time I observed there is correlation between the length of post and the its actual score. So I made the compare score a dynamic value.

Now the formula to compute the compare score is like this:

var quantifier = 1;

quantifier + ((quantifier / 16) * postLength / 64);

This bring a value of slightly greater than 1 if the length of the post is short but brings up a bigger value(slightly exponential) if the post length is larger.

After putting this in production, it works like a charm. Now it filters out most of the useless posts.

Take a look at the app in production. I may have to pull it in the future.

An interesting UX problem I came across today. Wondering why I never recognized it.

Alright so today’s post starts with an introduction to getting started with openshift, so that I won’t forget how to set it up in the future.

Install ruby > install rhc > set git > create a new app via rhc or the openshift online console > If you haven’t already - setup rhc > Try git clone > if it doesn’t work - rhc sshkey (to generate new keys and upload them automatically) | Or - re-install git and do everything again.

Depending on your current setup, it should take from 10 minutes to 2 days of brain numbing madness.

There was a guy in the beginning. Let’s call him Herb.

Herb is your typical introverted geek who loves to code. He becomes shy in front of strangers and especially girls.

So place this guy in a testosterone filled environment and he goes back in his shell. And that is what exactly happened with him when he found himself in a nightclub on Friday night.

Enter Mark. This guy was a bit short and quite honestly, had nothing special about him. But oh boy was this guy loaded with pizzazz. This guy comes in an hour late but when he comes, holy shit do you see the ladies swooning on him.

And so Mark and Herb were talking in a quiet corner of the club when a sexy Russian walks past by. Mark apparently knows her and he introduces her to Herb. After she walks by, he asks Mark how did he know her to which he replies he doesn’t know her.

“Are you serious”

“Yeah man I have never seen her in my life”

“So why did she talk to you like you know her”

“Because I whispered to her ‘You look really sexy, have you ever been in an orgy?”

At this point, Herb had a wild crazy expression of a person who had just discovered water.

Mark was just grinning, looking at his newest disciple and promptly took him under his wing for the night.

Sometimes when designing new things, I need to go back and retrospect my past work.

That is when I came across this

And that is when I remembered I stopped blogging.

This calls for a new design. But this is more of a revitalization of the old blog theme.

The new redesign takes elements from the old theme and removes unnecessary clutter. The header font is still montserrat mainly because it complements georgia Merriweather so beautifully.

The most drastic yet minimal change would be the color scheme. In the past, I used to write down hex codes on a pad. Now after making colorbook, it has become an indispensable tool for designing color schemes. Also, since I started using LESS, managing different color codes and other random variables has become much easier.

Another tool I used is gulpjs. My whole workflow is automated to minify and automatically inline css inside html. 

The result : It is better than the old one while still retaining its style and simplicity.

Last night, I was at a pub with a good friend of mine. We were discussing what is the next best thing in tech. In a semi-drunken stupor, I replied that we are not going through a revolution with tech, only evolution.

Sounds really cheesy but here is what I have observed.

Mobile phones have been around since the 1980s. They aren’t going to go away anytime soon. But the way we interact with the device has changed. Earlier, we had hard physical buttons which has been replaced by touchscreens.

Maybe in the future we will have holograms and voice only interaction for some devices. But the medium will stay.

Just like this blog.

string(92) "/srv/users/serverpilot/apps/shash7/public/wp-content/themes/shash7/templates/posts/image.php"
Warning: include(/srv/users/serverpilot/apps/shash7/public/wp-content/themes/shash7/templates/posts\text.php): failed to open stream: No such file or directory in /srv/users/serverpilot/apps/shash7/public/wp-content/themes/shash7/template-home.php on line 35

Warning: include(): Failed opening '/srv/users/serverpilot/apps/shash7/public/wp-content/themes/shash7/templates/posts\text.php' for inclusion (include_path='.:/opt/sp/php7.1/lib/php') in /srv/users/serverpilot/apps/shash7/public/wp-content/themes/shash7/template-home.php on line 35

Recently, I had a hard time configuring my domain on appfog. There were two seperate problems along the way.
One was properly setting up the a record along with the cname and the other was redirecting naked urls to www urls.
This is how I did it.

Set up appfog

Setting up appfog is a piece of cake. Just dowload their ‘af’ gem and login into appfog. From there, push and update your app in the desired infrastructure.

Set up your domain

For this post, I will be using the www domain name. It doesn’t matter whether your domain starts with www or non-www(usually called a canonical domain) so just decide beforehand which type of domain do you prefer.

Unlike other hosting providers, appfog doesn’t provide a dns server. So you need to set up an A record and a CNAME record with your domain provider.

For the A record, add the domain in appfog’s console. Like this :

See the second domain? That’s mine. The third one is min too but I will explain it later on. You will be provided a default domain which is the first one in the screenshot. Add your domain and click on update.

Now see the two ip addresses next to the A record on the screenie? You need to add those as two different A records on your domain provider’s console(or whatever it is called)

Next, add the CNAME record. The C in CNAME stands for canonical btw. I bought my domain from bigrock which is pretty nifty. My settings page looks like this :

Remember to NOT add the www when adding the A record. Now when adding the CNAME record, add the url next to the CNAME record in the appfog console as your CNAME value and add the www version of your url in CNAME. One last thing. I added the third domain because I couldn’t redirect from my domain provider’s console. So I set up the non-www url and redirected all the non-www traffic to the www-domain from my app itself.

Done? Dns propogation for A and CNAME records usually take between 1-4 hours so go outside and chill out.

Now your www-yourdomain-com will be working. That’s fine but when you type yourdomain-com without the www, it won’t work. That’s because you need to add a 301(it means permanent) redirect from your .yourdomain-com to www-yourdomain-com There are a couple of ways to do this.

  • Your domain provider has a facility to redirect domains. Simply set the redirect from your domain provider’s console.

  • If you are using apache, checkout the online guides on how to add redirects in .htaccess

  • Or if you are like me and hack around in nodejs, add this snippet of code before all your other routes.

app.get('*', function(req, res, next) {
        if (req.headers.host.slice(0, 3) != 'www') {
            res.redirect('http://www.' + req.headers.host + req.url, 301);
        } else {

This code snippet is meant for expressjs but it can work on standard nodejs http as well. The best part about this snippet is that it will redirect all paths to the correct domain.

That’s all for now folks. Setting up domains on appfog can be a bit of a pain but I hope this post helps.

gulpjs is a new kind of taskrunner. It is like gruntjs but much better. The work of a taskrunner is to automate simple tasks like minifying files, compiling preprocessor css like less, etc.

This is how I started using gulpjs


As I said before, gulpjs is a taskrunner. It is based on streams the technicalities of which are beyond me but that means it is extremely fast.
But better than this, the api of gulpjs is straightforward meaning you can get up and started within minutes.

This is how my gulpfile looks like :

var gulp = require('gulp');
var uglify = require('gulp-uglify');
var concat = require('gulp-concat');

gulp.task('compress', function() {

gulp.task('default', ['compress']);

Pretty simple huh? gulpjs is much easier to use and this was one of the main reasons I started using it instead of gruntjs

Getting started

First, you will need nodejs. Once installed, start npm via the command prompt and install gulpjs globally. This is because you can start calling it anywhere.

npm install -g gulp

Done? Now, add devDependencies in your package.json which should be in your project’s root. For this example, I am using gulp-uglify and gulp-concat. The required task is to minify and then concat all javascript files.
package.json :

	"name": "example",
	"version": "0.1.0",
	"author": "shash7",
	"devDependencies" : {
		"gulp-uglify": ">= 0.2.0",
		"gulp-concat": ">= 2.1.7"

Now give the command ‘npm install’ inside the project root (where you package.json will be residing) After installing, make a file named gulpfile.js inside the project root.

// Dependencies
var gulp = require('gulp');
var uglify = require('gulp-uglify');
var concat = require('gulp-concat');

// The actual task. Note the pipe function
gulp.task('compress', function() {

// The default task
gulp.task('default', ['compress']);

After adding the dependencies, you will need to create a task. I have named my task compress which is exactly what it does. gulpjs needs a task called default which will be executed when you run the file. Inside the default task, call your task inside an array. If you want, you can also bind a callback function.
When everything is done, simply call gulp in your project’s root


That’s it. gulpjs will now check for js files inside a folder called js and then will minify and concat them all and place them inside a folder called dist and will name the new file as all.js
That’s all for now. I hope you find gulpjs as awesome I did.