PortfolioProjects I've worked on recently
Graph Algorithms Visualization
Graph Algorithms Visualization

Graph algorithms implemented and visualized in D3.

WhatsApp Team Inbox
WhatsApp Team Inbox

Commercial WhatsApp Business API Solution.

Distributed Concurrent Image Processing
Distributed Concurrent Image Processing

Scalable Kubernetes & Docker distributed system for mass-processing of image payloads.

Readily Chrome Extension
Readily Chrome Extension

Reading Made Easier. Made for enhancing focus and empowering readership among people.

React Awesome Popups
React Awesome Popups

A lightweight, extendable, fast performing, highly customizeable, production ready React Component that renders an animated set of popups.


An app for university students to find professional activities that match their interest.

Song Association
Song Association

A mobile social party game. A fun activity to test your lyrics knowledge!

Abigail Farm Supply Website
Abigail Farm Supply Website

An interactive responsive company website with custom display components on WordPress.

My Garden Online
My Garden Online

Live-stream every plant you buy. Take care of your garden with water and fertilizer from the comfort of your home online.

ArticlesWhen I'm not writing code, I write articles
5 Lessons You Only Learn at Work and Not School
workplacelearning and developmenteducationmental healthsoftware engineering
In this article, I describe important lessons I have learned from working in my first full-time job after graduating. My job was as an analyst programmer (essentially a software engineer with data analytics responsibilities).The lessons I detail below stand out to me since the problems we face at work simply would not appear in school. I believe that knowing these lessons early can help students appear more mature and prepare to excel in the workplace.1. Deadlines are loose and user-requirements are never well-definedJobs could be roughly divided into two categories, standardized jobs (e.g. in a manufacturing plant, front-line retail, etc.) and project-based jobs (e.g. consulting, software development, etc.), with the latter, of course, being more open-ended.For me, being in the software development industry, a lot of my work is project-based. It stood out to me that deadlines for projects at work are often arbitrarily set and postponed. In addition, project requirements are often unclear at the start. This constrasts with coursework projects in school where the deadlines are strict and the grading scheme is oftend standardized.This kind of ambiguity can cause stress, especially if it is unexpected. Of course, there are ways to handle it.With these in mind, to become an effective employee, it is important firstly understand that deadlines are more useful as a tool to communicate progress between departments. It is then important to give reasonable estimates on the time it would take to complete tasks. It is also crucial to ask critical questions about the project goals and definitions at the start of the endeavour.2. You need more than an end design, you need an action plan tooIn coursework projects, you will often design or implement a solution, and that’s it. However, at work, you will often have to deal with legacy systems. New projects often have to work completely with all the other relevant systems in the business. This means that the end design has to be backwards compatible with these other systems, and larger projects often cannot be released overnight.As such, part of the project is to break it down into smaller launchable modules, and also to detail how these modules can be incrementally relase. This is an additional layer of thought that never has to be done in school projects. This kind of thinking can only be developed over time by understanding both the legacy systems and objectives.3. Be effective even when dealing with ineffective managersThere are some managers that are often not clear when describing project requirements, and sometimes even the root objectives. This then leads to task requests that appear random.In these cases, it is up to the employees to ask critical questions and ensure that the project is driving business value, and that the assigned tasks would not be a waste of tiem and resources.In the end, it is important to understand that employees and managers have to work as a team to become a valuable business unit, rather than just managers assigning tasks to employees, and employees following what the manager says.4. You will never have all the skills neededThere are different levels of proficiency in skills (e.g. programming languages).The lowest of which is never having used such skill.The next is having used it before, but needing to read up on it to use it further.The highest is having used it enough to not need to reference external documents.In any project, it is almost impossible that an individual will have enough proficiency in all the skills to design the end product without doing additional research, or collaborating with experts in other departments.This is the reason why communication and teamwork are important in businesses.That being said, in order to do projects more quickly, individuals or individual units need to reduce interdepartmental dependencies since this type of communication can take forever.Individually then, in comparison to learning hard skills (e.g. a programming language or framework) the more valuable skill is to be able to quickly learn new systems, such as by reading documentation. It is also important to accumulate knowledge from other departments to make decisions quicker.A thirst for knowledge and flexibility to adapt and learn about new systems is a critical attitude to be successful in project-based roles.5. On the social side, your circle of friends will shrink to the team you work withAs you become occupied by work, all your friends will also be busy with work, and it will get more difficult to arrange time with groups of friends.As humans, we are social beings, so maintaining good relationships outside of work is critical to our mental health, and by extension critical to our effectiveness in the workplace.Ways to tackle this issue is to get involved with activities in other departments or for other interests outside of work. In addition, meeting up with friends individually will be easier than with groups of friends.ConclusionThere are numerous challenges in the workplace that is simply not meant to appear in school. The lessons I have highlighted in this article are mostly soft-skills related (e.g. dealing with ambiguity, managers, relationships), but also have implications on the hard-skills that you focus on. In general, these problems can be addressed with the right mindset and patience, but it is also valuable to be prepared to face these challenges down the road.

Aug 26th, 2021

A Solid Review for the Fujifilm X-T20
mirrorless cameracamera reviewfujifilmoutdoorsphotography
This is a review for the Fujifilm X-T20 camera. I have used the camera for over 4 years, and here are the pros & cons to consider when purchasing this camera.Check out my album taken with this camera here.My Fujifilm X-T20 cameraWhat is the Fujifilm X-T20?The Fujifilm X-T20 is a compact medium-size, mirrorless digital camera. Since it is mirrorless, it uses an electric viewfinder.The camera takes up to 4000x6000 pixels (4K resolution) photos, and recording 4K video @ 30FPS or Full HD (1080p) @ 60FPS.The camera comes with either of the following kit lenses:XF 18–55mmXC 16–50mmIn general, most review will recommend the XF 18–55mm for higher quality.The average price of the Fujifilm X-T20 is about HKD 7000–9000 (USD 900–1200), but you can get it for cheaper.The lens I use are:XC 16–50mm (for events and wide field of view)XC 50–230mm (for zoom and portraits)ProsLightweight, CompactOverall, due to the mirrorless nature of the camera, it is very lightweight and compact. It is easy to hang on one shoulder while walking around and as such, it is not a hassle to bring around the streets as compared with larger cameras in the Digital Single-Lens Reflex (DSLR) group.Having mainly used a large DSLR camera (Canon 7D) before, the Fujifilm X-T20 feels quite small at first, but after getting used to it, its small size comes as a great benefit.Electronic ViewfinderTilting LCD monitor — FujifilmIn my experience of using the camera, I find that the electronic viewfinder shows a real-time display that closely represents the final picture you would take. It has very little-latency, which simulates a normal viewfinder.The camera also features a tilting touchscreen LCD monitor. While the tilting is useful for high-up or low-angle shots, the touchscreen is somewhat less useful since it gets dirty with fingerprints if you use it often.Auto SoftwareWhile many photographers despise using Picture mode (AKA “P mode”)in cameras due to its simple, unchallenging nature, the auto software (the equivalent of “P mode”) in the Fujifilm X-T20 consistently gives great results and is relatively quick. The photo quality and aperture/shutter speed adjustments are great for quick shots.Furthermore, since the auto mode is a switch, you can easily flip the switch and manual set the aperture, shutter speed, focus, etc. for your stylistic custom shots.Online DocumentationThe documentation for editing the settings on the Fujifilm X-T20 camera is also very clearly and completely written on Fujifilm’s website. This is very handy when you want to find out how to transfer files to your phone, or capture HDR images for example.ConsWith every product, there are drawbacks and trade-offs that have to be made.Zoom & focus can be slowIn terms of lens and software, the speed of zooming and changing focus can be relatively slow. This is especially crucial for fast-moving subjects such as in sports or wildlife photography.Some effective methods to counteract this is to use the Continuous High-speed shooting (CH) with Continuous Auto-Focus (AF-C) mode.Guide photos from FujifilmBattery Life LimitationsSince the camera is so compact and lightweight, the battery life can be a limitation. This limitation is common with all mirrorless cameras. The battery life is rated at 350 shots (CIPA).Based on reviews and my experience, the life of the NP-W126 / NP-W126S battery can last about 3 hours of continuous usage (this is not a standard test though!). Because of this, it is recommended to buy and charge an extra battery.In my experience, you can make the battery last a whole day’s trip and over 800 shots by turning the camera off whenever not in use and turning it on only when taking the shot since the start-up speed is fast.Phone Transfer is SlowThe Fujifilm camera comes with a free Fujifilm mobile app called Camera Remote. It allows the user to wirelessly transfer photos from their camera to their phone.In conjunction with the battery life limitation, the app is only useful for transferring specific photos to your phone on-the-go, especially with the limited speed. Since the battery life is limited, it is often better to connect the camera to the computer to charge the camera while transferring the images directly for post-processing and sharing on social media.ConclusionOverall, the Fujifilm X-T20 is an amazing product that consistently outputs great, crisp photos. With its compact, lightweight and sturdy construction, it is lovely to carry around and great to work with.

Aug 19th, 2021

A Visit to the Hong Kong Wetland Park
photographywildlifehong kongwetlandsflowers
In this article, I describe my journey through the beautiful Hong Kong Wetland Park.The Hong Kong Wetland park features a vast landscape filled with beautiful wildlife and heritage of Hong Kong. It also features an immersive exhibit of different wildlife species (with top-notch quality!) and an interactive museum.All the photos in this article were taken by me at the park with my Fujifilm X-T20 camera (check out my review here)!Wetland Park Viewing AreaGetting ThereThe park is located in Tin Shui Wai, Hong Kong.Given how far it is about an hour or longer from the city, it is best to get there by bus, rather than the railway (MTR).The park opens at 10am and closes at 5pm (be sure to check the updated website). That being said, the park has so much activities and sights to see that it is worthy of a full-day trip.At the time of writing, it only costs HKD 30 for adults to enter the park, which is very much worth the price!PhotographyThe rest of this article features photos of the various scenery and species in the area.LandscapesFlowersButterfliesBirdsCrabsDragonfliesSpidersFishOthersConclusionThe Hong Kong Wetland Park is a wonderful place to visit. It is filled with diverse species and high-quality museums. I highly recommend visiting this place and viewing the wonderful scenery and wildlife!

Aug 19th, 2021

4 Must-Have Linux Commands for Software Developers
productivitysoftware developmentlinuxdebugging
If you are a software developer, chances are you will be dealing with Linux systems and having to debug code. The best way to debug existing software is to find logs related to the issue, thus saving you loads of time enabling you to understand the situation and determine the best solution.Personally, debugging is not my strongest suit, but it is essential to be an effective developer. Since learning these commands, I have become an excellent solver of production issues as well as developer of new software. As such, I hope they can help you too.The four commands: cat, grep, less, and find, are important when you want to debug in an existing Linux machine.catCourtesy of wallpapercaveWhat is cat? Do I mean the animal cat? Unfortunately not! In Linux, cat (which stands for concatenate) is a command to sequentially output the content of a file in the command line.To use it, you can simply run the following:cat your-file.txtYou would then get the contents of the file:contents of the fileline 2 of the fileline 3, other contents etc...This is great for quickly printing out current configurations and short log files, but it isn’t actually very useful by itself. To unlock cat’s power, we need to know about the next command.grepWhat is grep? grep (which stands for globally search a regular expression and print) is a command that can search for the occurences of specific content and printing the lines in the file of those occurences. This is especially useful when used with the pipe ‘|’ command to pass the output of cat into the grep command as follows:cat your-file.txt | grep contentsIn the command, we take the contents of the file and search for the occurences of the word ‘contents’. We get the following output:contents of the fileline 3, other contents etc...How is this useful?This is especially useful when searching logs for a specific identifier, like an order id or account id. This can then help you track down the exception that occurred relating to the specific identifier.Another useful case is to determine if a specific pattern (e.g. the word ‘Exception’) occurred in the log file, thus allowing you to determine the weight of an issue, whether it is critically affecting numerous users, or a specific few.BONUS: You can chain the output of the grep command with the wc command using the paramer -l to output the line count as follows:cat your-file.txt | grep contents | wc -lYour output in this case would then be2lessIn some cases, the log file may be too large, thus using cat would print WAY too much content, or using grep would not show you other parts of the errors in the file. In these cases, less is here to save the day!(As the old adage goes, “less is more!”)What is less? It is an interactive command in Linux to show you a small portion of a large file at a time. It also allows you to navigate the file with arrow keys, or jump to certain lines with certain commands. The following are commands that are very useful for using lessG : Jump to the start of the fileshift + G : Jump to the end of a file/ : Search forwards for a pattern? : Search backwards for a patternHow less can helpWith these commands, you can find the occurence of an identifier or an exception (e.g. with shift+G then ?1234 to find the last instance of the id 1234) and find surrounding log output to better understand the issue.findFinally, if you do not know the location of the log file (which is usually the case in projects with a lack of documentation!), you can use find to locate possible log files.What is find?find is a command that outputs the filenames in a directory which contains the pattern that you indicate. It searches the directory with recursion, thus helping you find files where you might not have guessed.The basic usage of find is:find {location} -name {pattern}For example, the following command searches the current directory . for all files containing the word “log” (e.g. server.log). The * is a wildchard character to match any stringfind . -name "*log*"Be warned!Using find at the root directory / as shown below can take a long time since it will search all the files in the system. The command will print out all the files in the system since we do not include a -name argument.find / ConclusionThere you have it! Using the commands cat, grep, less, and find can help save you a great deal of time, thus allowing you to find the root cause of an issue earlier and become an efficient developer.4 Must-Have Linux Commands for Software Developers was originally published in CodeX on Medium, where people are continuing the conversation by highlighting and responding to this story.

Aug 6th, 2021

Financial Planning Made Easy with New Data Visualization
appsweb developmentfearfinancial planningdata visualization
In this article, I share a website app that I built to empower people to plan for their future. I believe that knowledge & planning is the key confidence. The app makes it easy to add incomes, expenses, and goals, then see how they impact your future through a graph, as well as how you can change them.https://medium.com/media/79ca4630cdfd381ea577fff76d687d3c/hrefFear is only a matter of uncertainty. I believe that if we know what the future looks like in our current track, we can make changes in our lifestyle or expectations before it is too late.Check out the financial planner here!Interactive Projections GraphThe main feature of the app is an interactive graph of your projected savings, incomes, and expenses over time. This is generated from your inputs (i.e. incomes, expenses, and goals).In the app, you can see the amounts spent for items such as a house or car in any given year.You can also click and drag the house / car spendings left or right to adjust the starting date of the purchase!Interactive drag goal to modify start dateAll of your incomes are automatically taxed based on the region you have selected.You are able to view the amounts in any currency you select, such as Hong Kong Dollar, United States Dollar, etc. There are many more features I hope to add into the app, such as adding rental income, and so on.Most of the work now is in adding accurate tax calculations for the different incomes, such as salary tax, rental tax, property tax, investment income tax, etc. This way, you can just select your region and all the taxes are automatically applied! This would make it so much simpler to make rough yet accurate estimates for your future. Of course, for full transparency, the tax rates used are displayed for each income.Through this app, I aim to make it simple to plan your future and share it with others. I hope to make financial planning less of a burden and more of a fun activity to discuss with others.The app is available right now for FREE at: https://finance.justinsj.comFeel free to comment to add a new location or a new feature!Please also support this app by liking and subscribing to my channel and sharing the app with others!

May 30th, 2021

How to Code with Confidence
strategyintelligencesoftware developmentconfidenceprogramming
In this article, I discuss insightful tactics and strategies that I have learned to be confident in my implementations and save valuable time when programming. Through these, I am confident that the software I built works as expected, and if asked, I would be able to answer any question about the software’s behaviour.I hope that if you take these into consideration, you too, will be able to code with confidence, have more time on your hands, and experience clarity in programming.Credit to seventyfour — freepik.comThe Source of ProblemsFrom my experience building modules, fixes, and whole services ranging from startup to enterprise software, I have learned that much of the time consuming issues I have faced are in one of the following three categories:Trial and Error — Not understanding the librariesThis case often occurs when dealing with new libraries or new APIs. In my amateur years, I would use tutorial videos that show how to create a simple “Hello World” application and from that, build the components I need and inject them into my incumbent application.While this method is both an entertaining and fair way to start programming, it becomes infeasible when having to create custom logic, and most of the value in software comes from this custom logic. There are no videos for that.In another case, I would test parts of libraries in smaller environments by using “fiddle’s” such as JS Fiddle, Java Fiddle, and so on. However, I later realized that this is an extremely slow way to learn a new library. There is a seemingly simple yet understated solution, which is reading the documentation to fully understand the library, which is detailed later in this article.Runtime Errors — Not understanding the existing implementationsOne of the other common errors I have found from my experience are runtime errors such as NullPointerException in Java, C# (undefined object in JavaScript, Python), and Segmentation faults in C / C++.This type of error is often what causes whole systems to go down, because not all cases have been considered.This type of issue stems from not understanding the existing implementations and not fully contemplating the possible inputs to your functions.Logical Errors — Not understanding the use caseIn rarer cases, logical errors can occur in programming. The most dangerous types are those that occur rarely but have serious impact on the software. These errors could be deadlocks in the case of parallel programming, unhandled cases, etc.This makes it important to understand the use case of the program and formally list out what the specifications of the program should be.The SolutionThe following solution is divided into four parts, and each address the different problems you would face as a software developer.Coding with DocumentationFrom the errors detailed above, it is clear that understanding is key to solving these issues. Thus, reading the documentation is absolutely crucial to the solution.This solution stems from the wisdom in Sun Tsu’s adage in “The Art of War”:It is said that if you know your enemies and know yourself, you will not be imperiled in a hundred battles…Much of the time when searching how to use a library on Google, you will get results from Stackoverflow. You might find a question with a close enough situation as you are in, and try to copy code without fully understanding what each variable and function does.However, later on, you will find that when building software, you really need to be aware of all possible cases, otherwise you will find many issue tickets stemming from your “hacky” copy-pasted code.— — —Thus, take a bit of time to read the documentation and understand precisely what the inputs and outputs are, and what the functions would return in exceptional cases, and so on. These will significantly help reduce time wasted on compiling code, deploying it in your environment, and testing only to find a new exceptional case you have not considered.You can adopt this tactic in programming by simply adding “documentation” to your search queries.More importantly, reading the documentation will significantly build your confidence in that will you know how the software will behave in exceptional scenarios, and thus you could revise your code without having to run trials to find the errors.Re-read Your SolutionNext, it is almost impossible to whip up a perfect solution at the start, so taking some time to step back and re-read your solution from the perspective of a frustrated user can really help weed out potential issues before even running the code.Much of the time, logical errors occur when the program has not been carefully analysed. This could be because of pressure to complete the task in a short amount of time, but rushing the solution will not only not work, it will cause problems that show up as errors in the testing process.This is why programming is considered as much as an art as it is science. Great art takes time.A good mindset when re-reading your solution is to be looking for errors, and not to re-read your solution to justify that it works for the “happy path”.Invest Time in Setting Up Your IDEOne more really effective investment is on your Integrated Development Environment (IDE). Setting it up correctly to provide code completion and provide a list of available functions (e.g. IntelliSense in Visual Studio Code) as you write the code will significantly reduce the time you need to spend reading documentation, without risking misunderstanding the code.Also being able to find the references where variables are used and where functions are called will help reduce the time it takes to understand how a program runs.Setting up a Development EnvironmentFinally, testing your solution is inevitable. While most of the errors can be resolved in your mind while writing the program with the strategy above, it is also important that we are not perfect. Thus, you will eventually have to test the code in its destined environment.As a developer, it is also your responsibility to prepare this environment and be able to quickly deploy your solution to it.As a note of precaution, it is best to rely on this environment to look for bugs and instead only use it to validate that your software behaves as expected.ConclusionIn this article, I have discussed strategies and tactics to build bullet-proof software that you are confident in and are fully aware of its behaviour in any scenario.In summary, by being disciplined and focusing on solving errors without even running the code, you are able to speed up the coding process and have complete knowledge and confidence in your application.By being comfortable in reading documentation, you unlock the potential to write any kind of program, in any context, with minimal future maintenance — the dream of any programmer.How to Code with Confidence was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.

Feb 20th, 2021

How to Quickly Estimate your AWS Costs (with FREE spreadsheet template)
awsstartupcost estimationweb app developmentexcel
In this article, I provide a quick and easy-to-use method to estimate AWS costs for your app. The article comes with a FREE spreadsheet template that will help you make the estimations with minimal effort.Business photo created by snowing — www.freepik.comThe estimates you can do with the following are very rough estimates, different users will use your app differently, so do note that your actual expenses may vary accordingly.Estimating the cost of using AWS is important to planning any application, as it helps you estimate how much you would have to charge users at a minimum later on.The AWS price constants in the spreadsheet are based on one instance of AWS prices, and may vary as AWS changes their prices.Fixed vs Variable costsFixed costs are expenditures that do not increase as the usage of your app increases. Examples of these include rent or purchase of physical storefront, warehouses, etc. Of course, it is important to note that fixed costs may actually scale somewhat with your number of users. For example, a warehouse for $1000/mo may have only enough capacity for an estimated 100,000users, and for another 100,000 users, you will need to purchase an additional warehouse. This could me modelled better as a step function, where from 0–100,000users, your fixed cost for warehousing is $1000, from 100,001–200,000 users, your cost is $2000, and so on.However, for the purpose of this model using AWS, majority of your expenses will be variable, meaning they scale with the amount of usage. Thus, I leave one entry field for an estimated fixed cost, and the rest will be assumed to be variable costs.The SpreadsheetYou can copy the cost estimator spreadsheet here.The goal of the spreadsheet is to estimate AWS costs in a per month basis and scaled by an estimated number of users.Note that each AWS Pricing Constant has VERY specific units (per million, per GB/mo, etc.). Take note of these units if you wish to modify the spreadsheet to better suit your application.The example for this spreadsheet is an application to remind users to perform preventive maintenance for their properties / applicances. For example, an air conditioner in their apartment could be cleaned out every 2 months.You will find that a lot of assumptions are made when making preliminary cost estimations and these should be clearly stated.LegendYellow Cells: You should change the number based on your own caseLight-blue Cells: Resulting numbers you should pay attention toGrey Cells: Comments (could be removed)The Transaction TableThis table describes the multiplicity of various user-related transactions.Transaction Table exampleIn the example:1 user is assumed to have 10* properties on average. (e.g. air conditioner, washing machine, dryer, etc.)On average, each property is assumed to have 1* appointment for maintenance per month.Each appointment would have 5* related notifications (e.g. start, delayed, etc.)*It is good to slightly over-estimate these numbersThe second row estimates the total number of transactions by multiplying the number above it and to the left (see the equations for clarification)This shows that on average, each user may receive 50 notifications in a month (this could be optimized later by grouping the notifications).Note that the transaction table has NO assumption on using AWS yet, and it is solely based on the predicted usage of the application.The Component Usage TableThis is a table to describe how much a user will use different modules in AWS. Like the transaction table, this varies for every app, and this will be majority of what you have to fill in.Each row represents a component in AWS, while each column represents a related transaction.Component Usage Table exampleIn the column (b) for example, a single user is assumed to use the following components in creating, reading, updating, deleting (CRUD) a single property:API Gateway 5 timesLambda 5 timesDynamoDB 10 timesSES 0 timesIn column (e), we have the price constants from the AWS Pricing Constants sheet.Get Total AWS Component CostsIn column (f), we have the total estimated cost for using each AWS component (API Gateway, Lambda, DynamoDB, SES, etc.). This is acquired by multiplying each column with the estimated number of total transactions in the Transaction Table (see the equation in the sheet).Get InsightsThe pie chart below the Component Usage Table shows that the estimated usage of the AWS Simple Email Service (SES), would take up over 96% of the cost. That’s a large percentage and would thus need consideration on either optimizing the usage of SES, or finding alternatives to integrate into the solution.Fixed CostsSome of the fixed costs estimated in the sheet include domain name and hosting.Fixed Cost Estimates exampleUser-Scaled EstimatesThe user-scaled estimates in Section D show a table and graph of how the total costs (fixed + variable) would cost on a monthly basis.User-Scaled Estimates exampleIn the example, it is shown that the fixed costs are minimal if it was aimed for the app to achieve over 10,000 users in the long run.ConclusionThroughout this article, I have described a method to model user behaviour in an application, and how to create a table to calculate usage of AWS components.With the tables generated, estimates of component costs and total cost are calculated and actionable insights could be acquired from these calculations.Let me know in the comments if you’d love for me to create a user-based AWS cost estimator web application using the above concepts :)

Jan 8th, 2021

The Ultimate Guide for Quickly Launching Websites Using AWS & Namecheap
namecheapawsguides and tutorialssoftware developmentwebsite development
The Ultimate Guide for Quickly Launching Websites Using AWS & NamecheapIn this article, I will show you a step-by-step guide on how you can quickly and cheaply launch your website using AWS & Namecheap. In the examples, I will be using a ReactJS project, but the website could be built using any framework.Abstract vector created by vectorjuice — www.freepik.comStatic Web PageIf you are building a static web page, and have no intention of extending its functionality, you will be better off using a simpler hosting solution such as GitHub Pages. In there, you can drop your static build into the repository and it would be accessible.Complex WebsitesIf you are building anything more complex than a static web page, this guide is for you.I have used this guide for countless times to launch prototype websites, so I hope it will be helpful for you.1. Build your applicationIf you want to get started with ReactJS, you can use the following sub-steps1.1 Install Requirements1.1.1 Install Node & NPM1.1.2 Install create-react-native-appnpm i -g create-react-native-app1.2 Create the Applicationcreate-react-native-app {{project name}}2. Dockerization (Optional)If you are at that stage that you want to optimize your build process, you can use the following sub-steps to build a docker image for your app.2.1 Create DockerfileCreate a DOCKERFILE in your project folder with the following contents:Make sure to install dependencies first for caching benefits.FROM node:12.18# Install requirementsRUN npm install -g expo-cli# Install dependenciesADD package.json .CMD [“npm”,”install”]# Copy contentsCOPY . /# Run applicationCMD [“sudo”,”expo”,”start”,” — web”]2.2 Build Docker ImageBuild the image with the following command ( — network=host prevents slow dependency downloads):Note: test:v0 is the image name and tag separated by ‘:’docker build — network=host -t test:v0 .2.3 Run Docker ImageRun the image.The command parameters -p 3000:3000 opens the port for localhost access.You will need to replace 3000 with the port number of your application. ReactJS apps use port 3000 by default.docker run -i -t -d -p 3000:3000test:v02.4 Test the imageYou can now view the app via your web browser at:http://localhost:30003. Set Up the ServerThe following section uses the “free for the first year” AWS cloud offerings. I am not sponsored by AWS in any way. It is just easy to use their services!3.1 Acquire AWS AccountGo to this link to create an AWS account.3.2 Create EC2 Instance (CHECK YOUR REGION)When you open the EC2 panel, double check that your region is where you want to host your server.EC2 is essentially a server-hosting service where you can configure your whole VM.For this guide, I will use a Ubuntu 16.04 LTS image, which is Free-tier eligible.Make sure to create a key-pair and store the private key for accessing the server later on! It should be a .pem file3.3 Access the EC2 Instance3.3.1 Use the key pair you have stored to access the server using SSH.If you do not know how to do this, you can do the following:Windows (using PuTTY)Open PuTTYgen (right-click the PuTTY application on the taskbar)Click Load (an existing private key file)Select the .pem private key from AWSClick Save private key and store the .ppk fileGet the address of your EC2 instance on the AWS dashboardExample EC2_IP_ADDRESS:ec2–11–222–333–444.ap-east-1.compute.amazonaws.comOpen PuTTYCreate a new profile on PuTTY and set the following:Hostname: ubuntu@ec2-11–222–333–444.ap-east-1.compute.amazonaws.comPort: 22Go to SSH / Auth then in the Private key file for authentication, select the .ppk file you have generatedPress Open to connect to the serverOn your first time connecting, PuTTY will ask you if you want to add the key of the server to your list of trusted public keys. Select Yes.If you did not put ubuntu@ in the hostname, the default username is ubuntu with no password (since you have connected by a private key file).3.3.2 Install Node 12 or above on the machinecurl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -sudo apt-get install nodejs -ynode -vnpm -vYou should then see an output like:$ node -vv12.21.0$ npm -v6.14.11If you are using npm run build, you will also want to install serve in the serversudo npm i -g serve3.4 Install your Application in the ServerYou can do this by pushing your application to GitHub and running the following command in the server:git clone YourGitRepoUrlcd YourGitRepoNamenpm installnpm run buildserve -s buildThe application should now be running in the server (default port 5000)3.5 Open the EC2 Instance to Public Access (Port)3.5.1 Go to the EC2 Dashboard3.5.2 Select your EC2 Instance (Check your region if you cannot find it)3.5.3 Go to Security / Security Details / Security Groups3.5.4 Select the security group3.5.5 Click Edit inbound rules3.5.6 Add the following rule: (For testing only, you should remove this later)Type: CustomProtocol: TCPPort range: 5000Source: YOUR_IP3.6 Test Public Access (Port)Go to `<EC2_IP_ADDRESS>:5000` on a web browser to see if the page is accessible and running4. Get Your Domain Name4.1 Acquire Domain Name from an ICANN Providerwww.namecheap.comwww.name.comwww.godaddy.comorAWS Route 534.2 Create AWS Elastic IP Address4.2.1 Create the AWS Elastic IP Address in the EC2 dashboard. Let’s call that the EC2_IP_ADDRESS .4.2.2 Associate the EC2 instance to that IP Address4.3 Create AWS Hosted Zone in Route 534.3.1 Add the following A RecordsRecord Name: www.YOUR.DOMAINType: AValue: EC2_IP_ADDRESSRecord Name: YOUR.DOMAINType: AValue: www.YOUR.DOMAIN.4.4 Add Hosted Zone Nameservers to ICANN Provider4.4.1 Get the name server addressesThe name servers are listed in the Hosted Zone’s NS recordNS record example4.4.2 Add the name servers to the ICANN Provider’s redirection of name servers*. Below, I use Namecheap.*The changes on the name server may take 24 to 48 hours depending on the provider, it normally takes an hour or so to update.4.5 Open Port 80 (HTTP) on the EC2 Instance Security GroupDo this by adding the following inbound rules:Type: HTTPProtocol: TCPPort range: 80Source: HTTPProtocol: TCPPort range: 80Source: ::/04.6 Redirect Port 80 (default web port) traffic to Application Port (5000)4.7.1 Run the following commands anywhere in your serversudo iptables -t nat -I PREROUTING -p tcp — dport 80 -j REDIRECT — to-port 5000sudo iptables -I INPUT -p tcp — dport 5000-j ACCEPT4.7 Test Public Access (Port 80)Go to http://YOUR.DOMAINon a web browser to see if the page is accessible and running. You do not need to include the port number (80) since you are using http://.5. Set SSL Certificate (Get HTTPS on your website)5.1 Acquire AWS ACM SSL CertificateThis may take time (up to 24 hours) when Route 53 CNAME records are created, but it usually only takes less than an hour.5.1.1 Go to the AWS ACM dashboard5.1.2 Request a certificate for your YOUR.DOMAIN and www.YOUR.DOMAIN addresses5.1.3 Confirm the Request and validate your domain by adding the required CNAME records requested by ACM5.2 Create a Load Balancer with SSL Certificate5.2.1 Go to the AWS EC2 dashboard. Make sure the region is correct!5.2.2 Under Load Balancing go to Load Balancers5.2.3 Select Create Load Balancer5.2.4 Select Application Load Balancer (HTTP/HTTPS)5.2.5 Fill in the necessary details:NameAdd HTTPS ListenerAvailability Zones (you can select all)5.2.6 Click Next5.2.7 On Configure Security Settings, select the SSL certificate you have generated using AWS ACM, or another SSL certificate you have.5.2.8 Click Next5.2.9 On Configure Security Group, select the security group of your EC2 instance5.2.10 Click Next5.2.11 On Configure Routing, create a target group. You may use HTTPS for added security.5.2.12 Make sure to give the target group a name5.2.13 Click Next5.2.14 Select the EC2 instances you want to add to the target group5.2.15 Click Review, then Create5.3 Redirect traffic to Load Balancer on Route 535.3.1 Go to Route 535.3.2 Select the A record that fits the following parameters:Record Name: www.YOUR.DOMAINType: AValue: EC2_IP_ADDRESS5.3.3 Edit the record and select the load balancer you have created as the value (it may be called “dualstack….”)5.4 Open Port 443 (HTTPS) on the EC2 Instance Security GroupDo this by adding the following inbound rules:Type: HTTPSProtocol: TCPPort range: 443Source: HTTPSProtocol: TCPPort range: 443Source: ::/05.5 Redirect Port 443 traffic to Application Port (5000)5.5.1 Run the following commands anywhere in your serversudo iptables -t nat -I PREROUTING -p tcp — dport 443 -j REDIRECT — to-port 5000sudo iptables -I INPUT -p tcp — dport 5000 -j ACCEPT5.6 Test HTTPS Access to ApplicationGo to https://YOUR.DOMAIN on a web browser to see if the page is accessible and running.Congratulations! You now have an HTTPS Web Service hosted on AWS!6. Transfer Region (Optional)This is in case you wish to transfer the EC2 instance to a different region. The guide uses the Amazon Machine Image (AMI) to copy the instance and transport it across regions.6.1 AWS EC2 Instance Transfer6.1.1 Create AMI using EC2 (this reboots the instance!)To keep system running, rerun the npm run start or serve -s build command in the instance6.1.2 Copy AMI to new region6.1.3 Create the instance using the AMI in the new region6.1.4 Open the ports in the new instance6.1.5 Create static IP for instance6.1.6 Associate Instance to new static IP6.2 Load Balancer6.2.1 Request new ACM certificate IN THE RIGHT REGION6.2.2 Create new Application Load Balancer with HTTP & HTTPS listeners using new ACM certificate6.3 Route 536.3.1 Redirect www. A Record to new LB6.4 Run the Instance6.4.1 Connect to the instance via PuTTY6.4.2 Run the necessary npm run start or serve -s buildFor serve -s build running on port 5000, run the following commands after to open the ports (80, 443) on the server. The security group inbound rules should already be set on the EC2 instance configuration.sudo iptables -t nat -I PREROUTING -p tcp — dport 80 -j REDIRECT — to-port 5000sudo iptables -I INPUT -p tcp — dport 5000 -j ACCEPTsudo iptables -t nat -I PREROUTING -p tcp — dport 443 -j REDIRECT — to-port 5000sudo iptables -I INPUT -p tcp — dport 5000 -j ACCEPT6.5 CleanupYou can now delete the AMI (not the EC2 instances!) on both regions to avoid additional costs.

Jan 1st, 2021

How to Implement the Memento Design Pattern for ReactJS
reactjsmaintainabilitysoftware developmentdesign patternsobject oriented
In this article, I discuss how the Object-Oriented Memento Design Pattern can be implemented in ReactJS. The base code could be downloaded at the end of the article, but I highly recommend reading the article first to understand how to use it!Memento Design Pattern Component DiagramMemento Design PatternFirstly, it’s important to understand what the Memento Design Pattern is for and how it can help you in making bullet-proof code. This means that a small investment in upfront complexity will pay off as code you don’t have to touch again down the road.The Memento Design Pattern abstracts the interface for storing the state of objects without breaking encapsulation. This means that only the same class will know how to save and load its state, thus preventing any bad cross-class dependencies. The pattern also creates Memento objects, which can be loaded and reloaded back at any time, allowing the client object to revert its state.As a developer, this also means that once this is implemented, you no longer have to worry about how the states are saved, and instead can focus on what parts of the state you wish to save in any new component.Memento uses the following components:Virtual Memento ClientConcrete Memento Client(s)MementoThe Concrete Client inherits the Virtual Client’s interface and calls the load() and save() functions at desired points in its React.Component lifecycle.The load() function will typically be called in the React.Component constructor(props) function, or in the componentDidMount() function.export class ConcreteMementoClient extends VirtualMementoClient { constructor(props){ super(props); this.load(); } //...}Meanwhile, the save() function will be called in any user function that requires saving the state information after changes have been made. For example, the function could be called in a userDidAction(), as a callback:export class ConcreteMementoClient extends VirtualMementoClient{ // constructor(props)... userDidAction(){ // Do stuff... const state = this.state; // get the state this.setState(state,this.save); } //...}Note that this.setState(state,callback) takes two arguments, the new state object and the callback. In this case, the save() function is used as the callback.Below is an example for ConcreteMementoClient.js/* ConcreteMementoClient.js */import {VirtualMementoClient} from './VirtualMementoClient';export class ConcreteMementoClient extends VirtualMementoClient{ constructor(props){ super(props); this.load(); } userDidAction(){ // Do stuff... const state = this.state; // get the state this.setState(state,this.save); } }.Here is the implementation of the VirtualMementoClient.js for you to see how the getKey(), getSaveData(), and loadSaveData() are called:/* VirtualMementoClient.js */import React from 'react';import {Memento} from './Memento';export class VirtualMementoClient extends React.Component { getKey(){return "";} save(callback=()=>{}){ const saveData = this.getSaveData(); // Call an external storage implementation const key = this.getKey();. this.memento = new Memento(); this.memento.setState(key,saveData); } load(callback=null){ //Set the callback to this.onLoadComplete for default callback = callback ? callback : this.onLoadComplete; if (!this.memento){this.memento = new Memento();} // Call an external load implementation const key = this.getKey(); this.memento.getState(key,(data)=>{ data = data ? data : {}; // Set default data to {} this.loadSaveData(data, callback); }); } getSaveData(){return this.state;} loadSaveData(data,callback=()=>{}){ if (data){ this.setState(data,callback); } else { callback(); } } onLoadComplete(){} // Virtual function}An example of the Memento.js (this varies based on where you want to store your data!).In the example below, the Memento uses the chrome.storage API to store and load the data. This is intended for use in a Chrome Extension./* Memento.js */export class Memento { setState(key,data,callback=()=>{}){ if (!key) return; const saveData = {}; saveData[key] = data; chrome.storage && chrome.storage.local.set( saveData, callback ); } getState(key,callback=()=>{}){ if (!key) return; chrome.storage && chrome.storage.local.get( key, function(result){ callback(result[key]) } ); }}The Memento’s interface is then called through the Virtual Client’s implementation.The following sequence diagram shows how this works:Memento Design Pattern Sequence DiagramTwo processes are shown in the diagram above: (1) Saving, and (2) Loading.(1) SavingThe Concrete Memento Component calls this.save(), which triggers the implementation in the Virtual Memento Client.The Virtual Memento Client then calls getSaveData(), which is implemented in Concrete Memento Client.The Concrete Memento Client returns the necessary data.The Virtual Memento Client then calls setState() on the Memento to store the data.(2) LoadingThe Concrete Memento Component calls this.load(), which triggers the implementation in the Virtual Memento Client.The Virtual Memento Client then calls the getState() function of the Memento to load the data.Once the data is loaded from the memento via a callback, the Virtual Memento Client calls the loadSaveData() function in the Concrete Memento Client.The Concrete Memento Client then processes the data as needed and triggers its onLoadComplete() callback at the end.CodeDownload the code at: https://github.com/JSANJ/MementoConclusionUsing the Memento code above, you can flexibly store and load state in any component by just declaring the implementation of the virtual functions, thus minimizing the amount of code needed to be written for new components and reusing the Memento framework.You can now rest easy knowing the state of your objects will be saved and loaded as expected.How to Implement the Memento Design Pattern for ReactJS was originally published in The Startup on Medium, where people are continuing the conversation by highlighting and responding to this story.

Dec 25th, 2020

The BEST Naming Strategy for Any Programming Language
maintainabilityjavascriptnaming conventionsbest practicessoftware development
In this article, I write about a best practice naming strategy for functions that I find amazing to work with. It encapsulates responsibilities among different kinds of functions and sets guidelines that will save you a lot of debugging time down the road.The naming strategy is suitable for any programming language, but I will focus on JavaScript (using ReactJS) and use the example of function implementations in Readily, a reading enhancement Chrome Extension for dyslexic readers.Following this, the criteria for the best naming convention would be:Shortest names possibleEasy to understandReadily LogoExample of Readily FeaturesNaming Conventions != Naming StrategyFirstly, while I won’t get into too much detail into case convention, but here are the most recognized ones for completeness.camelCase : all words except the first are capitalized at the first letter (JavaScript)PascalCase : all words capitalized at the first letter (C#)snake_case : all lowercase, words separated by underscores (python)High-Level OverviewNow, the key concept in this naming strategy is adding prefixes to functions to indicate to declare what will happen when it is called. This allows future developers to quickly identify where in the code any business logic was implemented incorrectly given a set of debug logs.Note that this article does not discuss a naming strategy for variables. That will be in an article for another time.Prefixes, Why?Using prefixes encapsulates what occurs in functions using the single responsibility principles, meaning that functions should ever only do one thing, or make one kind of decision.This method is used in the Unity game engine’s networking module, which requires functions that will be run on the server to start with Cmd while functions that can only be called in the clients start with Rpc (short for remote procedure call. More on this here.The kinds of prefixes you will use can depend on your use case. For the example below, I will be discussing general functions with regards to using the Command and Memento Design Pattern .The COMMAND pattern is applied to the SentenceMenuItem, which is the row rendered in the example image containing the “Sentence” title and toggle switch.Following the MEMENTO pattern for ReactJS, all STATE must be in the top level renderer object (SentenceMenuItem). In MEMENTO, functions must update the state, and changes in the state must be analyzed to reflect visual updates. This is done via the virtual componentDidUpdate(prevProps,prevState,snapshot) in the React.Component class where this.state can be called in the function to get the current state.In the example, there are a few states to be kept for each webpage visisted:current (integer), indicates the sentence number the user is onhighlights (map), indicates which sentences should be highlighedcommands (array-like), stores the command historyFunctions are prefixed with the following keys:Prefix Table[1] The commands object most closely resembles a stack. A command is pushed to the object to be at the top. However, when undoing, the top command is just popped and discarded. The undone commands are kept until a redo is executed or the user applied a new command to overwrite the popped commands. The popped commands could be stored in another stack.Further Notes on PrefixesdoIterMay contain filtration logic. Execute functions should not be called here as it will trigger multiple state updates.Instead, the final state should be calculated using calc then applied using execute, the differences in state should then calculated by calc, and then be iterated by the doIter function.userThe compoennt’s enabled & active state is checked before the command functions are allowed to run. Execute functions may be directly called if undo functionality is not intended.calc & getAll variables should be declared in the function parameters (this should not read any state variables). Constants may be declared outside the function.Additional FunctionsFor ReactJS, the following function is also used:componentDidUpdate: compare previous state and new state, then apply do functionsExample FlowHere is an example of how these functions are used. In it, you can see how the encapsulation makes it clear what would happen in the functions./*** The following chain will increment the this.state.current * value to indicate that the next sentence should be* highlighted.*/userMoveNextSentence() // Calls the command function to // record the action - commandMoveNext() // Calls the execute to apply state change = executeMove(commandProps) // Causes the re-render - (state-change re-render) - componentDidUpdate() // Calls the do functions to // remove the previous // highlight and add the next one - doRemoveHighlight(prevN), doAddHighlight(nextN)ConclusionIn this article I have discussed the best naming strategy for encapsulating several types of functions. Using this naming strategy, developers can significantly enhance the maintainability and understandability of their code.If you have any thoughts or knowledge of the enforcement of this prefixing (e.g. in a Linter), do comment and let me know below!

Dec 17th, 2020

VideosI also make videos