APIs and API/REST Clients

An API is essentially a programmatic way for you to interact with a system. When online services provide an API it can allow for a huge opportunity of customisation and extendability.

  • Practically all social media tools like Buffer, Sprout Social, Hootsuite would be utilising APIs provided by Facebook, Twitter, Instagram, etc in order to build their app.
  • Features of these apps would be limited to what the API allows: this is why you probably don’t see any Google+ integration as Google hasn’t release any API that lets you post updates!

But whenever starting to play with an API you’d probably start looking at the docs to understand how to make calls or if they have any sample code/libraries to get you going. Sometimes setting up a test environment can be time consuming so this is where raw API requests that utilise cURL are great! You can run the requests straight from the command line: see an example below from Intercom’s API to list users

curl https://api.intercom.io/users \
-H 'Authorization:Bearer <Your access token>' \
-H 'Accept: application/json'

I started off using cURL but after a while I needed something that

  • was less prone to breakage (e.g. missing out a \ or a ' causing malformed/incorrect requests)
  • was easy to switch between different requests
  • provided extra features for extensibility (e.g. if I wanted to switch access tokens to connect to a different environment, I would have to change the request to use the correct token)

Meeting Postman

That is when I met Postman. Their tagline of “Postman Makes API Development Simple.” did certainly ring true to me.

Postman annotated.png

Postman provided

  • Folders for categorisation of requests
  • Different environments and variables: so that I can quickly switch credentials between different development/test/production environments
  • Multiple tabs: enabled me to make a request in one tab and switch to the next tab to see any related changes

The came Insomnia (of the good kind)

After a while, I got a bit tiresome of seeing Postman’s loading/splash screen and it felt like it took quite long to start up. While it has so many features (such as being able to use it for testing), I didn’t really need all of them so I was on the look out for something simpler and quicker.

Then I found Insomnia with its lovely https://insomnia.rest/ URL

Insomnia Annotated.png

It has almost all the features I need and is even open source! My two main issues are

  • No tabs: so switching between requests can be a bit tiresome but workable (I still utilise Postman when I do need to do more efficient switches)
  • It auto saves requests: I have a template request which I modify and it automatically saves it: so that means my template is gone and I could have lost documentation on how to make the request and thus relying on going back to the API docs to find the full details. Postman only saves the template request when you actually request to save it. Perhaps since Insomnia is open source I could bring this up as a feature request or even implement it myself
Postman Template.png
Postman with my request template
Insomnia Template Gone.png
Insomnia with my request template overridden by last request

Insomnia & Postman

  • Free
  • Cross platform (Windows/Mac/Linux)
  • Folders for categorisation
  • Environment variables and switching
  • Import/Export function
  • Keyboard shortcuts
  • Online account/sync option
  • Proxy Support
  • Themes


  • Pros
    • Cleaner interface
    • Quicker startup
    • Open source
  • Cons
    • No tabs
    • Requests auto save
    • Online sync requires a paid subscription


  • Pros
    • Multiple Tabs
    • Requests do not auto save
    • Free online sync
    • More features
  • Cons
    • Slower startup
    • Cluttered interface

API/REST clients such as Postman and Insomnia will definitely be something I’ll keep in my toolkit and it has helped me so many times from being able to debug Firebase Cloud Messaging, TelegramSlack and more

So the next time you find yourself looking into APIs, perhaps look for a Postman collection to see if that can help you get things started up and running quicker


Sublime Text Plugin Quickstart

Based on the fact that the Sublime Text plugin example page is outdated below is a quick guide to create a Sublime Text Plugin for Sublime Text 2

  1. Go to Tools > New Plugin to auto generate a template for a plug-in
    import sublime, sublime_plugin
    class ExampleCommand(sublime_plugin.TextCommand):
        def run(self, edit):
            self.view.insert(edit, 0, "Hello, World!")
  2. Save it as a .py file in Packages/User folder (it should be the default folder when you select save). I chose testPlugin.py
  3. You can run in from the Sublime Text console (Ctrl + ~ in Windows) using the following command. (if it doesn’t work try, try saving the file again with the console open to see any errors and also try closing and reopening Sublime Text)

Running Camel Case Commands

Use underscores

class ExampleTextCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        self.view.insert(edit, 0, "Hello, World!")

sublime.Edit & sublime_plugin.EventListener

If an edit object is needed (seems to be needed for writing things on the page), use view.begin_edit() but don’t forget to end_edit()

They can be created by view.begin_edit(). Every call to view.begin_edit() must have a corresponding call to view.end_edit(), typically wrapped in a try … finally block.

Sublime Text 2 API reference

The EventListener class let’s you trigger things on an event happening and the code below shows inserting text to a document when it is opened. (Disclaimer: I’m not fluent in Python so I’m not sure if the below is fully correct but it does seem to work)

import sublime, sublime_plugin
class OnOpenCommand( sublime_plugin.EventListener):
   def on_load(self, view):
       try :
           edit = view.begin_edit()
           view.insert(edit, 0, "on load")
       finally :

Quickstart to Android Flashing Custom ROMs

Bootloader Android

I know I was a bit confused when initially rooting and installing custom ROMs on my Android device and while I don’t consider myself an expert there are a few terms that could use a quick definition to know your way around custom ROM installations.

Device Modes/States

When you start your device you can boot into 1 of 3 modes

  • Bootloader: a mode that can boot into Recovery or start the regular boot process (into Android) and also shows some details of your device. ROMs can be flashed in the bootloader but it is not the typical case
  • Recovery: a mode to flash ROMs (stock / custom)
  • Regular system boot: boots into the operating system while would typically be Android

Communication Tools

These tools can be used to communicate and even transfer files with your device

  • adb: when in recovery mode / standard Android
  • fastboot : when in bootloader

Unlocking the Bootloader


Boot loaders can be locked which prevents custom ROMS from being flashed. Unlocking the bootloader can be done with the following commands (this was done on a Nexus 7 2013, other devices may need other commands)

  1. Reboot into the bootloader
    adb reboot bootloader
  2. Unlock the bootloader
    fastboot oem unlock

Bootloader unlockBootloader unlock icon

Once the bootloader is unlocked you can install a custom ROM. While I believe it is possible to install custom ROMs without a custom recovery program, the typical way to install a ROM is with one. I’ve used ClockWorkMod Recovery and Team Win Recovery Project (TWRP) but there are others other there. Just make sure you install the right one for your device.

Flashing a Custom ROM

Custom Recovery TWRP

  1. Install a custom recovery
  2. Install it on your device
  3. Download your custom ROM
  4. Reboot your device into recovery
    adb reboot recovery
  5. Follow the on screen instructions to install the ROM
    1. Typically you have to wipe your device (dalvik cache, system and personal data)
    2. Install the custom ROM from a zip file
  6. Reboot into your new ROM

Custom ROMS

  • Custom builds/implementation of Android with some famous ones such as CyanogenMod and ParanoidAndroid (currently I’m using OmniROM)
  • Stock ROMs are the original ROM that came with the device
  • Custom ROMs typically will not have the Google services and usually need to be manually installed. Typically packaged / called gapps
  • Some problem with custom ROMs is usually hardware support: some things may not work as well as they do on stock ROMs. Thus custom ROMs that are based on stock ROMs will probably have better hardware support compared to generic custom ROMs


Other Terms

  • “Unlocked”: this can mean several things
    • Unlocked from a carrier: it can us SIM cards from any carrier
    • Unlocked bootloader: it can load custom ROMs

Things I’m still unsure of

  • If the bootloader needs to be unlocked in order to flash a custom recovery
  • “Secure boot”: shown on the boot loader but doesn’t affect flashing a custom ROM


Quickstart: Git


  • A distributed revision control system
  • Doesn’t require a central server to work
  • Download at: http://git-scm.com/
  • Command line tutorial below, execute code blocks in sequence
  • Lines starting with # are command line outputs or notes
  • Available on GitHub CornerGeeks/test-git


git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
git config --list

# user.name=John Doe
# user.email=johndoe@example.com
# -- other config

git config user.name

# John Doe
  • user.name and user.email is what is recorded in commit logs


Go to a folder in command line and initialise it as a git repository

git init

# # Initialized empty Git repository in /Users/user/test_git/.git/

See current status and branch

git status

# # On branch master
# #
# # Initial commit
# #
# nothing to commit (create/copy files and use "git add" to track)    

Will show current branch and status of files in the folder

Save (Commit) files into the Repo

  • Create a file & add it to the staging area
    touch README
    git add README
  • See current status
    git status
    # # On branch master
    # #
    # # Initial commit
    # #
    # # Changes to be committed:
    # #   (use "git rm --cached <file>..." to unstage)
    # #
    # #    new file:   a
    # #
  • Commit the file
    git commit -m "Added README (C1)"
    # [master (root-commit) 93ecaa8] Added README (C1)
    #  1 file changed, 0 insertions(+), 0 deletions(-)
    #  create mode 100644 README
  • Can also commit with “git commit” then type in the editor and save

Status of Files

  1. Untracked: Will not be saved / commited into the repo (“git add filename” to stage”)
  2. Staged: To be saved into the repo (“git commit” to save into repo and make it unmodified)
  3. Unmodified: Previously committed. Currently has no changes
  4. Modified: Previously committed. Content has changed. Stage file (“git add filename”) in order to commit new version to repo
  • Cannot commit empty folders into git

Staging Files

  • A file needs to be staged before it can be committed
  • A staged file will stage the file at that point in time
    git status
      # # On branch master
      # nothing to commit, working directory clean 
    echo "line 1" >> README
    git status      
      # # On branch master
      # # Changes not staged for commit:
      # #   (use "git add <file>..." to update what will be committed)
      # #   (use "git checkout -- <file>..." to discard changes in working directory)
      # #
      # #    modified:   README
      # #
      # no changes added to commit (use "git add" and/or "git commit -a")
    git add README
    echo "line 2" >> README
    git commit -m "commits only line 1 (C2)"
       # [master 58001d6] commits only line 1 (C2)
       #  1 file changed, 1 insertion(+)      
    git status
      # # On branch master
      # # Changes not staged for commit:
      # #   (use "git add <file>..." to update what will be committed)
      # #   (use "git checkout -- <file>..." to discard changes in working directory)
      # #
      # #    modified:   README
      # #
      # no changes added to commit (use "git add" and/or "git commit -a")      
    git commit -am "auto stage tracked files and commit (C3)"
       # [master cbf5a24] auto stage tracked files and commit (C3)
       #  1 file changed, 1 insertion(+)

Viewing previous commit logs

git log
git log -2
git log --pretty=oneline
git log --pretty="format:%h: %s (%an)"

See previous commit states

-Checkout the state of the repo at any commit

# git checkout previousCommitHashShownInGitLog

git log --pretty=oneline

  # cbf5a24f41bb8a2f70527f5a96cea4fca411910b auto stage tracked files and commit (C3)
  # 58001d6d9c474a6e5b102cf53a1948b0f5fd213d commits only line 1 (C2)
  # 93ecaa8c1238b872827781f6136401e4b9e3849b Added README (C1)


  # line 1
  # line 2

git checkout 25555caa7589363b20b3e1b34bd7ba979c13ff57

  # line 1

git checkout master

  # line 1
  # line 2
  • Think of commits as chain of events linked to the previous commit
    C1 - C2 - C3 <-- master <-- head
  • master is the default branch and points to the last commit in the branch
  • HEAD points to you current location in the commit chain (changes when you checkout)
  • Checking out will move the head pointer and shows the state of the files at the point in time
  • “git checkout master” will point the HEAD back to master which is the latest commit
  • Note: All version of files are stored locally so you can git checkout without any network

Ignoring Files

  • Specify in .gitignore folder
    touch ignore_this_file
    git status
      # # On branch master
      # # Untracked files:
      # #   (use "git add <file>..." to include in what will be committed)
      # #
      # #    ignore_this_file
      # nothing added to commit but untracked files present (use "git add" to track)
    echo "ignore_this_file" >> .gitignore
    git status
      # # On branch master
      # # Untracked files:
      # #   (use "git add <file>..." to include in what will be committed)
      # #
      # #    .gitignore


  • When working on a new feature, create a feature branch, work on it and then merge it into the master branch

View Branches

git branch
    # * master

    # C1 - C2 - C3 <-- master <-- head

Create New Branch

git branch new_feature
    # C1 - C2 - C3 <-- master <-- head
    #           ^
    #           '---- new_feature

git branch
    # * master
    #   new_feature

Switch to new branch

git checkout new_feature
    # Switched to branch 'new_feature'

    # C1 - C2 - C3 <-- master
    #           ^
    #           '---- new_feature <-- head

git branch
    #   master
    # * new_feature

echo "new feature" >> README

git commit -am "new feature added (C4)"          

   # C1 - C2 - C3 <-- master
   #           |
   #           '---- C4 <-- new_feature <-- head

Merging Branches

  • Merge changes from new_feature into master
    git checkout master
      # C1 - C2 - C3 <-- master <-- head
      #           |
      #           '- C4 <-- new_feature
    git merge new_feature master
      # Updating e7578b4..13107de
      # Fast-forward
      #  README | 1 +
      #  1 file changed, 1 insertion(+)
      # C1 - C2 - C3 
      #           |
      #           '- C4 <-- new_feature 
      #               ^
      #               '---- master <-- head
  • As master has not been changed, the master pointer just “fast forwards”

Delete Branch after use

git branch -d new_feature

    # C1 - C2 - C3
    #           |
    #           '- C4
    #               ^
    #               '---- master <-- head

Merge Conflicts

  • Happens when conflicting changes happen between merges
      C1 - C2 - C3 - C4 <-- master
  • Create new branch and switch to it (shortcut)
    git checkout -b merge_conflict
    echo "merge_conflict_branch" > README
    git commit -am "one line README in merge_conflict (C5)"
      # C1 - C2 - C3 - C4 <-- master
      #                |
      #                C5 <-- merge_conflict  <-- head
    git checkout master
    echo "master add new line" >> README
    git commit -am "yet another line (C6)"
      # C1 - C2 - C3 - C4 - C6 <-- master  <-- head
      #                |
      #                C5 <-- merge_conflict
    git merge merge_conflict master
      # Auto-merging README
      # CONFLICT (content): Merge conflict in README
      # Automatic merge failed; fix conflicts and then commit the result.
  • Will now need to edit the README file manually to resolve conflicts
     cat README
       # <<<<<<< HEAD
       #  line 1
       #  line 2
       #  new feature
       #  master add new line
       #  =======
       #  merge_conflict_branch
       #  >>>>>>> merge_conflict
  • New file shows the changes between the branches.
  • Delete and clean the <<<<<<, =======, >>>>>> and text in between.
    • “<<<<<<<” : start of your current branch’s file
    • “=======” : end of your current branch’s file & start of the difference from other (merged) branch changes
    • “>>>>>>>” : end of other branch changesgit commit -am “merged merge_conflict with master (C7)”
       # C1 - C2 - C3 - C4 - C6 -C7 <-- master  <-- head
       #                |
       #                C5 <-- merge_conflict

Show changes

  • Changes that haven’t been staged
    echo "diff me" >> README
    git diff
      # diff --git a/README b/README
      # index 4b7c1e3..f6a1b72 100644
      # --- a/README
      # +++ b/README
      # @@ -4,3 +4,4 @@ new feature
      #  master add new line
      #  merge_conflict_branch
      # +diff me
  • Changes that have been staged
    echo "diff me again" >> README    
    git diff --cached    
    git add README
    git diff --cached
      # diff --git a/README b/README
      # index 4b7c1e3..fbe856c 100644
      # --- a/README
      # +++ b/README
      # @@ -4,3 +4,5 @@ new feature
      #  master add new line
      #  merge_conflict_branch
      # +diff me
      # +diff me again

Unstage a file

echo "to be unstaged" >> README
git add README
git status

  # On branch master
  # Changes to be committed:
  #   (use "git reset HEAD <file>..." to unstage)
  #    modified:   README

git reset HEAD README

  # Unstaged changes after reset:
  # M    README    

git status

  # # On branch master
  # # Changes not staged for commit:
  # #   (use "git add <file>..." to update what will be committed)
  # #   (use "git checkout -- <file>..." to discard changes in working directory)
  # #
  # #    modified:   README
  # #
  # no changes added to commit (use "git add" and/or "git commit -a")

Restore file to previous version

echo "these changes will be reset" >> README
git status

  # # On branch master
  # # Changes not staged for commit:
  # #   (use "git add <file>..." to update what will be committed)
  # #   (use "git checkout -- <file>..." to discard changes in working directory)
  # #
  # #    modified:   README
  # #
  # no changes added to commit (use "git add" and/or "git commit -a")

git checkout -- README
git status

  # # On branch master
  # nothing to commit, working directory clean    

Reset all tracked files to previous commit

git reset --hard
  • Deletes all changes since last commit
  • Only affects tracked files
  • Untracked files do not get deleted

Working with remotes

  • (e.g. GitHub, your own server, etc)

Push Changes to Remote

  • Add a remote to you bare repo
  • “git push repo_name branch_to_push”
    git remote -v
    git init ../git.git --bare
    git remote add my_repo ../git.git 
    git remote -v
      # my_repo  ../git.git (fetch)
      # my_repo  ../git.git (push)
    git push my_repo master
      # Counting objects: 24, done.
      # Delta compression using up to 2 threads.
      # Compressing objects: 100% (14/14), done.
      # Writing objects: 100% (24/24), 2.07 KiB | 0 bytes/s, done.
      # Total 24 (delta 1), reused 0 (delta 0)
      # To ../git.git
      #  * [new branch]      master -> master

Clone from a remote repo

  git clone ../git.git ../git_clone
  cd ../git_clone
  git remote -v
     # origin    /Users/user/test_git/../git.git (fetch)
     # origin    /Users/user/test_git/../git.git (push)      
  • “origin” is the default name of your git repo that you have access to

Download changes from a Remote URL

  # git fetch remote_name
  git fetch origin
  • Does not merge into your existing code, just downloads all changes locally so can merge / checkout

Merge Changes from Remote Branch

  git fetch origin
  git merge origin/master master
    #  **fix any conficts if needed and commit**
    # can also do "git pull origin"

Workflow for pushing to a Repo

  • Clone from Repo
    git clone url_to_git_repo
  • Go into directory and make changes
    cd url_to_git_repo
    echo "cloned" >> README
  • Commit your changes
    git commit -am "my changes"
  • Fetch and merge from origin
    git pull origin
  • Fix conflicts (if any)
    git commit -am "merged origin to masteR"
  • Push to origin
    git push origin master

GitHub Pull Requests

  • Fork a project
  • Clone locally
  • Add remote to project you forked from (typically called “upstream”)
    git remote add upstream git.repo
  • Make your changes
  • Make your commit
    git pull upstream/master master
    *resolve conflicts*
    git commit
  • Use web interface to create pull request
  • Go to your fork
  • Sidebar > Pull Request

Note: Markdown was a pain. It rendered the HTML but a mix of tabs and spaces and even manual spacing caused inconsistent behaviour.

MongoDB – Quick Start Installation and Usage

2 weeks back I attended yet another RHoK Melbourne event and ended up working on a project with NodeJS & MongoDB: both unfamiliar territories for me and thought it would be a good opportunity to create a quick start guide: here is the MongoDB one

Installing and Running the Server

  1. Get the binaries on the download page (http://www.mongodb.org/downloads) and get the necessary download for your platform (Windows/Linux/OS X/Solaris). Following commands will be based on OSX but similar actions can be one on other platforms
  2. In a terminal, navigate to where you downloaded the package and extract it
    cd ~/Downloads
    tar -zxf mongodb-osx-x86_64-2.4.8.tgz
  3. Create a folder to store your database
    cd mongodb-osx-x86_64-2.4.8
    mkdir db
  4. Start the server specifying the folder created
    bin/mongod --dbpath=db

Terminology coming from the typical relational database world

Relational Database MongoDB
Database / Schema Database
Table Collections
Row Record
Field / Column Field

Quick start of the MongoDB Shell

  1. Connect to the server
    Navigate to the folder where the files are extratcted, run the mongo Javascript shell  (which has tab completion)

    cd ~/Downloads/mongodb-osx-x86_64-2.4.8
  2. List / show databases
    show dbs
  3. Select a database (no need to created a database)
    > use unicorn
    switched to db unicorn
    > db
  4. Show collections (tables)
    show collections
  5. Inserting a record (row in a table)Collections do not need to be initialised, they are auto generated.
    Below shows the output of the Mongo shell. system.indexes contains indexes for collections

    > show collections
    > db.unicorns.insert({name: 'Aurora', 
       gender: 'f', weight: 450})
    > show collections

    Mismatched fields

    db.unicorns.insert({name: 'Aurora', gender: 'f', weight: 450})
    db.unicorns.insert({name: 'Leto', gender: 'm', 
        home: 'Arrakeen', worm: false})


        name: 'Solnara', 
        loves:['apple', 'carrot', 'chocolate']})
  6. Listing / Querying records
    > db.unicorns.find()
    { "_id" : ObjectId("52b65132eb122da0e6dd19a9"), "name" : "Aurora", "gender" : "f", "weight" : 450 }
    { "_id" : ObjectId("52b6519127026146f128de90"), "name" : "Leto", "gender" : "m", "home" : "Arrakeen", "worm" : false }

    Items have _id auto generated. No need to set an auto increment field.

    Filtering and field selection


    Search by name and show only name and worm  fields

    > db.unicorns.find({name: 'Aurora'}, {name: 1, worm:1, _id: 0})
    { "name" : "Aurora" }
    > db.unicorns.find({
        $or: [{name: 'Aurora'}, {'name': 'Leto'}]}, 
       {name: 1, worm:1, _id: 0}
    { "name" : "Leto", "worm" : false }
    { "name" : "Aurora" }

    Paging and Limiting results


    Record Counting

    db.unicorns.find({'name' : 'Aurora'}).count()


       {$or: [{'name' : 'Leto'}, {'name':'Aurora'}]})
  7. Query Selectors
    1. Comparison:
      1. $gt / $lt ($gte / $lte): Greater/Less than (or equal).
      2. $ne, $in / $nin: Not equal. In / Non in
    2. Logical: $or, $and, $not, $nor
  8. Updating:
    Update first matching record

      { name: 'Aurora' }, 
      { $set : { weight: 10 } } 

    Update all matching records

      { name: 'Aurora' }, 
      { $set : { weight: 10 } },
      { multi: true }

    Update matching record but insert if doesn’t exist

      { name: 'Roooooodles' }, 
      { $set : { weight: 10 } } ,
      { upsert: true }
  9. Deleting:
    Deleting all records:


    Delete all matching records

    db.unicorns.remove({name: 'Aurora'})

    Delete only first matching record

    db.unicorns.remove({name: 'Aurora'}, true)
  10. Drop collection

Other Considerations

  1. No joins. But has embedded documents
    > db.unicorns.insert({name: 'Aurora', gender: 'f', weight: 1450, owner: {'name': ['You', 'Me']}})
    > db.unicorns.find({'owner.name': 'Me'}, {'name': 1, 'owner.name': 1, _id: 0})
    { "name" : "Aurora", "owner" : { "name" : [ "You", "Me" ] } }

Further References

Considering Android Development: A bit of basics and then some

Considering Android Development Slidedeck

This was the talk I gave at GDG Brunei DevFest 2013 and I aimed for the content to be basic and accessible with a workable app, so that the attendees could use it as a starting off point for the hackathon, should they want to learn how to build an Android app.

I should have published the APK on the Play Store before the talk so that people could have downloaded the app and see what I was building as part of the talk

Source code: https://github.com/CornerGeeks/GDGBruneiDevFest2013/

Melbourne Fringe Festival – Unofficial Offline Guide

Melbourne Fringe Festival Unofficial Offline Guide

A couple of weeks back it was time for the Melbourne Fringe Festival again and I was keen to see some shows and there was a heck of a lot of events to go to that it was pretty overwhelming to search through and I had issues with actually looking for events. Thought it would be a good time to learn some Python and use Zurb Foundation.

Source Code available at https://github.com/thewheat/melbourne-fringe-festival


Problems I faced when using the Melbourne Fringe Festival website

  • A lot of data 300+ events and with max items per page, there was still 9 pages
  • Searching relied too much of going to the event detail page, and having over 300 events, this would be very time consuming
  • Had to go to event detail page to view:
    • description of event (had to view page in order to find what the event is about: title and subtitle was not enough information)
    • dates
    • prices
    • venue
  • Couldn’t search by budget

Features of the Unofficial Offline Guide

  • Viewing all events on 1 page
  • Show all necessary info on list page (event description, dates, prices, venue)
  • Search by date, category, venue, cost
  • Offline access
  • Should work with lower end phones (pauses between searches)Image


SMARTER eVCS Android app source

It is now available at: https://github.com/thewheat/SMARTER-eVCS-Android

The Android app is currently meant to be used in conjunction with the SMARTER eVCS webapp but hopefully I’ll get time to upgrade both the Android app the make it a standalone app.

Also once again, anybody interested in helping in this community development project, do get in contact or just get the code, make some changes and submit pull requests.

Happy Software Freedom Day! Have some code!

Today is Software Freedom Day and as a user of technology you should think about the programs that you use and understand the importance of the free software movement.

Depending on who you talk to, “free” it can mean different things but in terms of Software Freedom Day, “free software” refers to freedom and not price. Some of the core beliefs of both free software movement is that computers users should have the freedom to:

  1. use the software for any purpose
  2. study the software and modify it to suit their needs
  3. distribute copies, either gratis or for a fee, and
  4. distribute modified copies to help their community

Do watch the following video for Richard Stallman (RMS) explaining Software Freedom Day and has some great insight into GNU and GNU/Linux


I thought it was appropriate that I release the code for the SMARTER eVCS as an open source project dual licensed under the GPL V3 and MIT License. As I previously mentioned I hope that this will foster some community development and be a point for people to involve themselves in a community project of a different kind that I believe has yet to be done in Brunei.

The code is available at https://github.com/thewheat/SMARTER-eVCS-webapp

It requires CakePHP for now and was built on an older version of CakePHP and somethings on the todo list are as follows

  • Move to AJAX instead of full page load for the user front end (admin can stay as is for now)
  • Responsive/Mobile site design
  • Using HTML5 and possibly Javascript MP3 playback instead of relying on Flash
  • User login with each user having ability to manage multiple profiles
  • Possible remove the need for CakePHP all together to make it lighter

Next up will be the Android app source code release and also deploying the demo app online for people to play around and test. In the meantime, anybody willing to support, contribute or help can leave a comment / fork the code / spread the news. Any and all forms of participation is truly appreciated.

Giving Back to the Community

A couple of months back I started attending some meetups here in Melbourne and over a month ago I was able to attend my BarCampMelbourne (my first BarCamp!) and it was a great experience. What struck me most as I look back, is that there aren’t any kind of meetups like this back home in Brunei, at least to my knowledge. Events and meetups such as these rely on people giving back to the community and for regular meet-ups, to be consistent about it.

At one meetup, there was a company saying that they wanted to open source part of their product in order to give back to the community but it would take time for them to do so as it would take time for them to sort out their code and make it nice enough to publish: especially since it would represent the company. Sometimes they also have to separate out what code that they can release as open source, as some code may be libraries used which they may not have rights to distribute. I acknowledge that no company wants to put out bad code or give out something that isn’t theirs to give, but I also acknowledge that it is a point for procrastination: an excuse or crutch to fall back on and also possibly thinking that the code/work isn’t good enough. Or perhaps that is just me.

I pledged to code the SMARTER Android app over 1 and a half years ago and I did deploy a webapp for them to use to internally as well as an Android app what utilized the exported data from the webapp. After that I was caught up in finishing up my work before heading off to Australia and I guess I fell off the wagon in terms of developing that system further and keeping in contact with SMARTER as a whole. So by next week I hope to open source both the webapp and Android app and follow up with them, if there is anything further that can be done. I know the programs aren’t perfect, I know the code isn’t perfect, I know that there is room for improvement and I know that there is work to be done.

Over the next few weeks I’ll try document what I’ve done and also future goals that we hope to achieve. I used the word ‘we‘ as I hope to get other developers / contributors on board. I want this to be a base for contributing back to the community of Brunei and I am open to contributors / suggestions / feedback.