How I made a web app to help improve English listening skill

English was my strong suit back in high school; However, recently, English has became the thing that occupied 30% of my mind everyday because I’m going to take the IELTS next year and there are not much time left :’( One major problem that I have is that I found it hard to distinguish between singular and plural nouns in the listening test. So I made this web app as a pet project and also somehow it can improve my listening skill (somehow….)

Let’s set things up !

First, to keep it simple and easy, I’m going to use gulp combined with browser-sync to compile sass and reload the browser everytime I change the code.

At the first step I used the command yarn init to create the package.json file. Yup, my app’s name will be EListen (I just pull it out of the thin air, not the best name but…’s a great name :D )

Afterward, I’m a lazy guy so I used this site to generate my gulpfile.js

I use atom to edit my code, and I set my “motivation image” at the bottom right of the editor using a package for atom called editor-background . Next, I created the src folder to keep all my source file and then I ran the command yarn install to install all the dependencies that was generated by the site above.

My project folder’s structure

Now, I’m going to test if the gulpfile is runable using the command gulp

Well, look pretty “good” for the first try :)) Luckily, I’ve seen this kind of error before and I managed to fix it using 2 command

yarn remove gulp-sass
yarn add gulp-sass

Ok, after about a minute, executing and installing the dependencies, the gulp command executed successfully.

Let the “code” begin !


To begin, I created a index.html file which will be the main page of our web app, and then, I added some link to the main.js and main.css file which are located in dist/scripts and dist/styles , respectively. But why not the src folder ? Because in the gulpfile.js I set the input folder to src folder and the output folder to the dist folder.

gulp.task('styles', function(){
errorHandler: function (error) {
.pipe(autoprefixer('last 2 versions'))
.pipe(rename({suffix: '.min'}))

Ok, let’s start with the entry layout, I made a quick design in Balsamiq Mockups

This is what user will see when they first enter the web app

Yeah I know, I can never be a designer :)) Anyway, this is how it look on the browser (this is chrome browser, who know what will happen if I run this on Internet Explorer ¯\_(ツ)_/¯):

Look pretty good ! Similiar to the main game section, I also made a quick design and then code it and test it on the browser

The plan

The plan that I’m going to use is to get a random noun from some website or api and then pick a random form of it (singular or plural) by using the code that I found from stackoverflow by pmrotule on this question (thank a lot mate ! ) and to pronounce that word I will use the ResponsiveVoice library. When the user hit the button, we will check the word that we’ve picked before if it’s singular or plural and compare with the button that the use hit. If the the user hit the correct button, then we will use the sweetalert library to display the message to the user.

Get a random word

After 1 night, searching and asking my friends, there was no api that I found convenient, so I picked this site to get the nounlist. I’m going to make a GET request to that site and get the noun list. Afterward, I’ll pick a random noun and return it. But there is a problem:

My reaction

Where can I host a text file and access it using js ? where ? pastebin is a good site but some ISPs in Viet Nam keep that host out of reach for some reason. Hmm…..Oh ! How can I not try github at the first time ? you idiot ! So I posted the noun list to github and the code worked perfectly. You can find the list here.

And the result when using that function:

Pick a random form (singular or plural)

As I mentioned on the plan, I’ll use the function that I found from stackoverflow by pmrotule on this question (thank again mate ! ) to pluralize and singularize words. So here is the function that I wrote to pick random form

function singularOrPlural(text){
var booleanList = [true, false];
var isSingular = booleanList[Math.floor(Math.random() * 2)];
return text.plural(isSingular);

The function above will pick the random boolean from the list to determine the text form and then use the plural function and pass in boolean picked at the last step. Example of plural function:

"texts".plural(true) // will return "text"
"text".plural(false) // will return "texts"
"text".plural() // will return "texts"


This part is pretty simple, we just need to call the speak function in the ResponsiveVoice library. The function is bellow:

function speakText(text){

Check if the user hit the right button

This one is quite simple too ! We can use the plural function again to check if the word was singular or not then compare with button. If the user hit the correct button, we will display the message using sweetalert.

var currentButton = $(this).text();
var isButtonSingular = () => {return currentButton == "Singular"};
var isWordSingular = () => {return word.plural(true) == word};
if(isButtonSingular == isWordSingular){
swal("Good job!", "It's the correct answer !", "success");
swal("You dumb !", "It's the wrong answer !", "error");

The source code

Well, that is the basic structure of the web app, you can now enjoy it at:

The source code is at:

Other ideas

Now you can try to improve the app using you imagination ! How about not just practice listening to one word, but one word in a sentence !

I hope this project can somehow inspire you guys for your next great idea, till next time, good bye !

Like what you read? Give Nguyễn Việt Hưng a round of applause.

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