resume blog post feature image

Top 5 mistakes that I made with my Resumé

What are the top 5 mistakes that I made with my Resumé?

As a previous international student in Australia, I went through a lot of hassle to find jobs in my field – which is Software/Web development. I made a lot of mistakes early on; and now looking back, I wish I can tell my younger self not to fall into these traps when crafting my first resumé, my life would be a lot different.

In this article, I would like to share some mistakes that I had when I wrote my resumé and apply for companies on recruitment websites like

Some Analysis

Your CV will most likely go through at least 3 types of people before getting you into the interview: the Recruiter, the Hiring Manager, the Technical Lead. Between these 3 types, only the Technical Lead has skills that are relevant to your position.

The Recruiter will most likely not reading your CV. Instead they rely on a bunch of filters to only look at CVs which they think have enough experience and skills for the job they are recruiting. For example, if they need to find a senior web developer, fluent in PHP and React.js; the filters they can use are PHP, web developer, React, etc.

The Hiring Manager will look at the CVs that the Recruiters send them. These people will most likely scan through the CVs and short-list them. They are likely looking for the ability of working in a professional environment, along with soft skills like team work, time management, organizational skill, etc.

The Technical Lead will read the short-listed CVs given by the Hiring Manager. He/she will read your experience and determine if you have enough skills to work in the position. They are the deciding vote to whether to hire you or not, since most likely they will be your direct manager if you are hired.

1. Customize your CV for EACH company

This is important, let me repeat it one more time. Customize your CV, For, EACH, Company.

You will see why later.

When I started looking for web development positions. I drafted myself a generic Resumé and basically sent it to many job posts on SEEK, without hardly reading up the job requirements. This turned out to be a serious mistake, as I did not have any call back from the positions I applied for. This continued for over 6 months, until my mother, who was a HR manager told me about the issue that I had.

When reading up job descriptions on recruitment websites, please please make sure that you understand what you need to do, what skills you need to possess; and what business the company is in. This is very important to custom tailor your CV to fit the job description.

Take a look at this example

What is required of the role:

  • Commercial experience in PHP and SQL-based databases (MySQL/MariaDB/PostgreSQL)
  • Experience with Javascript and jQuery
  • Knowledge of best practice development methodologies
  • Experience collaborating with clients and stakeholders
  • High literacy and verbal communication skills


The following would also be highly advantageous:

  • Experience working with Drupal, CodeIgniter or SugarCRM
  • Experience integrating web applications with third party APIs and web services
  • Knowledge with running basic Linux commands
  • Experience with managing Apache2 web servers in Linux


Responsibilities will include:

  • Gathering requirements, designing solutions, coding, testing, maintenance & support
  • Clear communication with stakeholders to ensure expectations are met and clients are happy with the result
  • Thorough documentation of code and support cases
 Your CV should display these skills:

Technical skills

  • PHP – CodeIgniter, Drupal
  • MySQL
  • Javascript – jQuery
  • Linux – Apache server
  • Agile development methodology like Scrum, Kanban

Soft skills

  • Time management
  • Communication
  • Documentation
  • Teamwork

As you can see, I update the CV based on the requirements of the position. This will help my CV go through the Recruiters’ filters and have a higher chance to end up on the Hiring Manager’s desk.


2. Limit your Resumé to 1-2 page

Resumé should be short and condensed. Talent acquisition people have tons of CV to go through every day. No one will read a 3-4 pages CV, simply because it is not worth the time. I was proud of my achievements in my university time, so I ended up writing a 4-page Resumé, which besides my family and myself, no one reads it in full.

Having a short, condensed CV will focus the reader to just the most important points about yourself. For example, if you get multiple scholarships during your study, which I did, then just select the most valuable scholarship instead of listing them all out. If you participated in many programming projects, select one or two projects that relate to the position that you are applying.

Do you want to read event a 2-page resumé? If not, there is a very high chance that the hiring people won’t.

sample 2-paged resume


3. Less formatting – more readability

Take a look at these resumé

fancy resume          simple format resume

The format is very impressive and memorable. However, like I said before, the hiring people look through thousands and thousands of CV every day. Having this impressive resume does not make a lot of difference if the hiring person cannot find the information he/she is looking for.

In the past, I used to have a fancy resumé template, with all the colors and columns. Then after a while, I find that when I come back and update the CV, it was a bit difficult to find the section that I need to update at a glance. And I realized that if even I cannot find the sections I need, what happens with the recruiter when he/she looks at my CV!?!

In conclusion, having a simple CV format like Edgar’s CV makes it easier for other people to read, and therefore increasing your chance to get pass the barriers to be hired. One more bonus tip is that you should export your CV to PDF format, that will prevent any format changes and section misalignment.


4. Use simple words

In my first CV, I used a ton of technical terms, thinking that I could impress the recruiters into hiring me. It turned out that the recruiters did not understand what I was talking about, and therefore they throw my CV aside. They are not recommend someone that they could not understand.

For example: if you are experienced with Dynamic programming and can use discrete mathematics to figure out the optimized algorithms for various problems. Instead of writing “Experienced in Dynamic Programming, developing optimized algorithms using Discrete mathematics”, let us write “Experienced in computer programming methods and able to develop optimized algorithms to resolve problems”.

Simple words will make people understand us, and your CV will more likely end up on the Technical Lead’s desk.


5. Ask for other people’s feedback

Back then, I thought the CV was an exposure of who I was. So I did not want other people to look at it. Fear of being judged clouded my mind, while I should have shown everyone before sending it off. Feedbacks are valuable, especially when they come from someone who has experiences in recruiting, or someone who is a business owner.



Those are my top 5 mistakes when creating a Resumé to apply for jobs. I hope you guys enjoy the post and have much success with your career.

For a better illustration, I attach my CV here so you can have a look and it may helps you with creating your first CV.

Please be sure to check out other blog posts here or leave a comment below if you enjoy the content.

How to upgrade PHP version to 7.2 on Ubuntu 16.10

I decided to upgrade the PHP version in one of my servers from 7.0 to 7.2 to live with the bleeding edge. The process went quite smoothly, except for the last step which I needed to do a bit research.


First thing’s first: check your current version

php --version

Also create phpinfo.php file in your /var/www/html directory

<?php phpinfo();

and run the file to be sure that both php CLI and apache version are the same.


The Upgrade

You can use a third-party repository to install the latest version of PHP. We’ll use the repository by Ondřej Surý.

First, you need to install the repository.

# install required package so you can add repository
sudo apt-get install software-properties-common

# install the repository and update the repository list
sudo add-apt-repository ppa:ondrej/php

Then, update packages in the system

sudo apt-get update && apt-get upgrade


Install PHP 7.2 (or newer version, you can just change the version number in the command)

sudo apt-get install php7.2


(optional) install PHP modules, depending on your needs. Note that the version of PHP has to be specified

sudo apt-get install php7.2-dev php7.2-zip php7.2-curl php7.2-gd php7.2-mysql php7.2-mcrypt php7.2-xml libapache2-mod-php7.2


Verify PHP version using the command line

$ php --version
PHP (cli) (built: Dec  7 2018 08:07:08) ( NTS )


Verify PHP version using phpinfo.php file we created earlier.

[email protected]$^%@$^, the PHP version is still the previous one!!! The reason is that apache is still running with the old PHP version. We will need to change that so the server can run with PHP7.2.

Let’s run the following commands:

# disable old php module
sudo a2dismod php7.0

# enable new php module
sudo a2enmod php7.2

# restart the server
sudo service apache2 restart

Verify the PHP version again, and it should be updated to our new version.

PHP version 7.2.13

If you want to upgrade to a different version of PHP, just change the version number while installing, and don’t forget to disable the old PHP module and enable the new one for Apache.

I hope this helps you with your work, and have fun upgrading 😀

React logo

React 16.6 new features: contextType, lazy, memo

In Oct 24, 2018, React 16.6.0 was published to npm. It brings a lot of exciting new features, including contextType, React.lazy() and React.memo(). We will discuss in depths of what they are and how will they change your React ecosystem.

In this blog post, I am going to assume that you already have certain experience with React, and have been working with React for a little while (mainly for understanding the tremendous advantages that the new features will bring us.


In React 16.3, Facebook released context API officially, shaking the foundation of state management systems like redux, mobx. In React 16.6, context API is further improved by introducing static contextType.

const SampleContext = React.createContext();

class WithContextAPIComponent extends React.Component {
  render() {
    return (
        {(value) => (<div></div>)}

class WithContextTypeComponent extends React.Component {
  static contextType = SampleContext;
  render() {
    const value = this.context;
    return (<div></div>);

// usage
<SampleContext.Provider value={{ name: 'Tuan Nguyen' }}>
  <WithContextAPIComponent />
  <WithContextTypeComponent />

With the sample above, we can see that with contextType, we bound the context value to the component itself, which simplifies one layer of nested component to be rendered. This suddenly looks like it is so much similar to how we use redux store!!!



This is very simple. It enables the same functionality of React.PureComponent for functional components.

const MyComponent = React.memo(function MyComponent(props) {
  /* only rerenders if props change */

Previously functional components will re-render every time its props change, regardless of value.

With React.memo(), now functional components will shallowly check whether props values have changed, and decide to re-render.


In my opinion, this is the most outstanding feature that React 16.6 offers.

Short description: it allows React components to only be downloaded from server on demand.

import React, {lazy, Suspense} from 'react';
const OtherComponent = lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <OtherComponent />

In the example, MyComponent will download OtherComponent only when it is needed.

This is very useful in tabular structure, where most users do not browse every tab content.


For more information, let’s check out the changelog at

Write automated script with Tampermonkey and Webpack

Recently I was pulled into an old web-based game called Ghost Trapper. The gist of it is, after a period of time, I can click on a button to trap a ghost, then a count down appears and I have to wait for the count down to stop until I can hunt ghosts again.

Then it hit me, why don’t I automate the process so that I don’t have to spend so much time to play anymore.

Here’s a screenshot of the game.

Ghost trapper screen image

Note the top left count down. Once it reaches 0, I can click that button again and continue hunting ghosts.

I look around for a solution for automating the process. There are quite a few options:

  • Python’s scrapy
  • Phantom.js or Casper.js
  • Puppeteer
  • Tampermonkey (Google Chrome only)

I have some experience in Scrapy, Phantom.js; so I was thinking, why not utilize what I have already known?

… Or I can jump into new things and learn how to do it.


I decided to go with the second option, and I chose Tampermonkey to do the work.


So I quickly wrote a small script to check if the button is active, and if so, click on it.

setTimeout(() => {
  if (!$('#huntBtn').hasClass('disabled')) {
}, 3000);

Simple, isn’t it?!

The problem is, I would like to have the script runs on multiple machines, and I want to synchonize the code in all machines, so if I update the code I’ll just need to do it once.

I ended up with the following structure:

  • A github project to host the code
  • Tampermonkey’s ability to refer to external javascript resources.

My Tampermonkey script

// ==UserScript==
// @name         ghost-trapper
// @namespace
// @version      0.1
// @description  Ghost Trapper auto
// @author       lightbringer
// @noframes
// @require
// @require      file:///Z:/nodejs/ghost-trapper/ghost-trapper.js
// @match*
// @grant        GM_setValue
// @grant        GM_getValue
// ==/UserScript==

My ghost-trapper.js

class GhostTrapper {
  constructor() {
    // do stuff
  hunt() {
    if (!$('#huntBtn').hasClass('disabled')) { 
  run() {
    setTimeout(this.hunt, 3000);

var gt = new GhostTrapper();;


Looking good, however, the script requires 2 files, one from jquery CDN. one from my local machine. And the speed is not very nice (took me a noticeable time before the hunt click happened).

I thought, why can’t I combine them into 1 file? I have experience in Webpack, so let’s try it out.


First I installed necessary packages

npm i --save jquery
npm i --save-dev webpack webpack-cli babel-core babel-loader babel-preset-env

Then I created webpack config file

// webpack.config.js

const path = require('path');

module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'ghost-trapper.bundle.js'
  module: {
    rules: [
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: "babel-loader",

Then I create a main file for webpack to point to.

// src/main.js 
import $ from 'jquery'; 
import GhostTrapper from './GhostTrapper'; 

const gt = new GhostTrapper();;


After all this, I compile webpack config. And voilà, the bundle is ready for me to include into tampermonkey, and it runs exactly what I wanted.

From then on, I added multiple features to my automation tool. The ease of webpack’s watch mode really helps me during development, as I just need to refresh the page and the new code is already deployed.