7 Things I Learnt From Building Pulangmengundi.com

Behind the scenes at carpool.pulangmengundi.com

Timothy Teoh
7 min readSep 19, 2018


In the run-up to the 14th General Elections, I was part of pulangmengundi.com, an initiative created for Malaysians helping Malaysians home to vote. It was an incredible experience, and I thought I’d share what I learnt, from a tech perspective (although as you’ll see, the non-tech parts were even more important!).

1. Ship fast, distribute the load, and seek out partners

The news spread quickly on Tuesday evening (April 10th) that GE14 was going to take place on a weekday — an obvious voter suppression tactic. By dinnertime the hashtags #undirabu and #pulangmengundi were trending in Twitterjaya, and people were already offering travel subsidies and organizing carpools.

I realized that a site to connect people requesting carpools and subsidies to people offering them would be useful. By 8pm I registered the domain and started asking around for a list of polling districts.

Barely three hours later, I got a message from You Jing (I would discover later it was actually his GF and sister messaging me) saying he had the same idea.

We quickly decided to split up, with me doing carpool.pulangmengundi.com in Laravel and React; him doing subsidy.pulangmengundi.com in Rails. My girlfriend Grace did up a landing page in Weebly.

After enlisting the help of some friends, the six of us decided we should launch by the weekend. This was ambitious, but shipping fast meant we had people on our platform sooner, and we were able to start working on other things in parallel.

After three sleepless nights we launched on Friday afternoon, and reached 30k users over the weekend. We rapidly built a core team and enlisted volunteers to help with things like support, development, social media, and graphics.

Most importantly, we reached out to other groups who were doing the same thing, in order to focus our efforts on different ways — we eventually came up with a strategic partnership with balik.undirabu.com who were providing sponsored buses. This all happened very quickly — we ended up at a press conference together the following Monday! — which might not have been possible had we taken longer.

Looking back, in the end it was this partnership which made our initiatives so successful as pulangmengundi.com had the tech, and balik.undirabu.com had the machinery and resources.

2. Know your deployment vendors

I have had the luxury of working with established build pipelines at work (Jenkins -> Signed RPMs, and S2I builds -> Docker images in Openshift). To my embarrassment I realized I didn’t actually know a way to put a new Laravel application into production quickly!

Time was of the essence, and I needed something that would:

  • Publish my Laravel application from Git
  • Expose environment variables separately and allow me to edit them quickly
  • Scale if it needed it to
  • Create its own database
  • Handle its own SSL

— All without requiring too much work, as I needed to spend the time coding instead of tinkering with deployments. The main thing in my favour was that the app would only need to be up for a month, so cost wasn’t a concern.

Luckily, my friend Ajay Madhukar had done some research previously, and recommended Fortrabbit. It had great Laravel support (in fact, most of Fortrabbit is powered with Laravel), and I managed to deploy to it in <15 minutes.

3. Be familiar with a CSS framework

Grace had come up with a logo (using Canva) that was simple and recognizable, and so we needed to theme our three sites around it.

I’m not the best at CSS and design — being more of a backend guy. I fortunately did have some experience using Bootstrap, and ended up using bootstrap-live-customizer.com which allowed me to customize and preview Bootstrap LESS variables on the fly.

Using bootstrap-live-customizer.com to quickly customize content

This tool generates theme.less and _variables.less files for you to compile with Bootstrap, and vice-versa (try importing these two files into the customizer).

I combined this with react-bootstrap, which abstracts Bootstrap classes so I didn’t need to memorize them, and voila, it looked like I knew my way around CSS! There were some alignment issues here and there (which I never got round to figuring out), but it was good enough.

4. Use analytics to inform decisions

An app launch is just the beginning — but without analytics and data, you’ll be flying blind. I’d consider putting in Google Analytics code as the baseline for any app, it’s so easy.

Just go analytics.google.com, create a tracker, and put it in a section of code that is loaded by every page in your site.

carpool.pulangmengundi.com — GA stats from our first weekend

Google Analytics quickly showed us that a whopping 93% of users were arriving from mobile. This led us to ensure that our sites and emails were always mobile-first.

Of course, GA also gave us basic visitor figures, and tracked inbound links so we knew whenever we got write-ups in the news.

By sending an event to GA whenever the search feature was used, we knew exactly which routes users were searching for.

We were able to share the popular routes with balik.undirabu.com who were providing sponsored buses (you can also see that Johor is so big that people also needed help travelling within Johor!)

5. Know a web framework and an ORM inside-out

It’s true that opinionated frameworks and database ORMs tend to lower performance or provide to much abstraction — but they do so while increasing productivity and readability. It’s absolutely worth the time to have a framework of choice with which you can quickly pump out code.

Our subsidy team was swamped with work, but meanwhile we had donors and partners (thousand-dollar whales, if you will) who were willing to sponsor requests in bulk, e.g. flights for all East Coast students, to a certain state, or charter student buses.

I had never worked with PostgreSQL before, but because I was very familiar with Laravel’s Eloquent ORM, I was able to help out by building an admin that pointed to our subsidy database. Because the ORM abstracted out all DB operations, I didn’t even need to be familiar with PostgreSQL.

We were then able to filter out users that matched the criteria of our donors, and proceed to verify them so our donors could fulfill their requests.

6. Always be able to contact your users, and be wary of relying too much on Facebook

April 2018 was the height of the Cambridge Analytica scandal, which left us very reluctant to store user information — too reluctant, as it turns out. We even considered not storing email addresses at all, relying instead on Twitter/Facebook/Google user IDs.

We initially allowed the user to show either their email address, contact number, or Facebook account.

This was nearly a disaster for us — initial versions of our apps displayed a link to the user’s Facebook profile so people could contact each other. Unfortunately Facebook introduced a change that broke all profile links, making it hard for people to even find each other on Facebook.

In retrospect, we should have required both emails and contact numbers upfront, instead of overthinking it.

Emails (we used Mailgun) were important to quickly disseminate new information and update users. We went on to regularly send emails to our carpool users about new matches and new partnerships. Note that Mailgun requires a manual vetting before they allow you to send too many emails.

Whatsapp was by far the most reliable way to contact users, and none of them complained about this. Most were actually grateful and excited!

7. Don’t neglect the human aspect, and don’t assume how users will use your app.

While we achieved success and publicity on the back of having platforms to connect carpoolers and people needing subsidies, a lot of “closing” was still manually done through Whatsapp.

Our volunteer Geok Hui organized carpoolers into individual Whatsapp groups based on their destinations, which turned out to be the best way to connect carpoolers. They liked this so much they asked if we would organize balik kampung rides too!

On the subsidy side, we spent weekends messaging hundreds of individual recipients to verify their identities from supporting documents.

We had also assumed that our users would use our sites in this sequence:

  1. Ask for carpool/subsidy
  2. Get connected to someone offering carpool/subsidy
  3. Close request after being successfully connected

Can you see the problem here? Think about it…

…Yup, step #3 never happens :P

I hope you found this interesting! I’m also making the source code for carpool.pulangmengundi.com public (don’t judge!), should anyone want to carry the torch in GE15.

Thanks again to the team and all the donors and carpoolers who made this happen!

This post was originally posted on TribeHired.