KKMIN

Creating a personal portfolio website

If you're reading this, chances are you got here through my portfolio website. Let's discuss some core ideas and inspirations I had during the development of the website.

Tech stack

The project was made entirely in Typescript and CSS via the React Framework with no additional UI libraries. This proved to be a great learning experience, as I found that my familiarity with CSS was particularly shallow.

My previous projects relied on UI libraries like Material UI, which was great, but styling components from the ground up with CSS gave one a better appreciation of the foundations and fundamentals in UI/UX for the web.

I was also new to Typescript and took this as a learning opportunity to expand from Javascript. Typescript has been becoming increasingly popular for frontend development in favour of Javascript, due to the fact that it is essentially a superset of Javascript with type-enforcement.

I found that there was more boilerplate code that needed to be written in comparison to Javascript due to Typescript's strict nature regarding types, but this additional hassle is a small price to pay for type-safety in my opinion. A lot of run-time errors will be reduced due to this enforcement, and we end up saving time that might have been wasted trying to debug.

Tabs

One of the core features of the website, which was also what kickstarted the website itself, is the tab-based navigation. Each tab acts just like your browser tabs, displaying their own respective contents. The initial implementation of the tabs came from a frontend assignment that was given to me by a startup for an internship position, and served as an inspiration to modify and repurpose it for the portfolio website.

The most important thing for the tab components to function properly is state management, i.e keeping track of which tab is active and to render the correct content properly. In React, state management can be done via the useState() hook, which was good enough for this project. For larger scale and more complex state management, Redux is an option.

Reusable Components

Scalability and reusability were of high priority for this project, since certain things such as list of projects would be growing as I progress in my career. Information regarding projects were stored in a JSON file with appropriate nesting, and these objects were mapped to a custom Project Card component. This ensures that any amount of projects can be displayed by simply adding a new project object into the JSON file.

Animations

As I dabbled with CSS stylings throughout the development of the website, I discovered that we were able to make animations in CSS from simple motions (rotate, translate, scale) to more complex combinations involving CSS properties. Surprisingly, despite seeming like it would be a daunting task to create animations, CSS provides a simple and effective interface to create animations with its keyframes.

The basic idea is to specify how the object of interest would look like at varying stages of animation (0%, 25%, 50%, 100%) via CSS properties and keyframes, and CSS would fill in the blanks for you.

I took advantage of this in combination with setTimeout() to chain CSS animations of different components one after another. (E.g. Tabs appearing after Welcome message disappears). Unfortunately, there doesn't seem to be a way to chain animations of different components in pure CSS, which would have been useful. Perhaps I should take a look at Javascript libraries to explore animations further.

Lock

The Lock puzzle on the Contact page was the culmination of all the concepts involved in the website. Since the contact page contains personal information, I thought it would be a fun idea to create a mini puzzle to deter spammers (Although I do not know how effective it would be against bots).

There are two main components to the mechanism, the lock itself and the unlocker sequence. When the content for Contact is rendered, we first generate a secret 4-digit number where each number is between 1 and 4 inclusive, and distinct from each other. This number encodes the sequence in the unlocker.

Next, the unlocker animates based on this sequence to highlight to the user the correct sequence. During this animation, the user cannot interfere with the unlocker by trying to click or reset, which was done with state management.

Afterwards, the user can enter the sequence, which stores a number based on the order they clicked. This is matched against the original number to determine if an unlock is possible. If it is not possible, the lock turns red with a small animation. The user can press the reset the button to re-render the component, resetting the secret number adn restarting the process.

Otherwise, the lock is unlocked and the information behind is shown. This component combines both state management as well as animation chaining, which needs to be done in a coherent manner to prevent tamperinng / visual bugs.

Closing thoughts

All in all, this project was a fun journey that tested and further solidified my fundamentals while exposing me to new things. It may not be the slickest or most mind-boggling frontend project out there, but it is something I can take ownership and be proud of.

← Back to home

Comments