I rebuilt my portfolio after 2 years
Tags: showdev, nextjs, typescript, career
Published: 2022-04-16 04:40:24

It's gonna be a long article with many boring things all about me, I believe it's fair to think that some of you just want to see my portfolio. So here you go:
* [Old version](https://web.archive.org/web/20220509014455/https://khang-nd.github.io/)
* [New version](https://khangnd.info/)

----

So, after 2 years in the software industry, I officially hit the first milestone of pursuing my passion for front-end development. I was offered the front-end developer role at an [Australia-based company](https://unios.com/) at the beginning of this year. It was a pleasant coincidence for which I neither searched nor applied for the role I was offered, and the guy who reached out to me was neither an HR nor recruiter, he was a fellow developer who was simply impressed by my silly [pet](https://github.com/khang-nd/7.css) [projects](https://github.com/khang-nd/win7). He is now a colleague and a senior who is always supportive and proactively helps me out in my work. And even better, the working culture here is surprisingly flexible and respectful, I have full control over my time and save a lot of commuting cost and time, as I'm working remotely from home, connecting with the Aussie team via MS Teams, or whenever I feel like to, I'm always welcome at the local office in Vietnam. Lucky me!

Anyway, that was a little bit sharing of my current status, and you may be wondering, why the hell did I rebuild my portfolio if I wasn't looking for a change of job? Yep, that's a valid question, I rebuilt my personal portfolio website after 2 years, not to impress the recruiters, not to find a new job, but to pick up the new tech stack I use at my current job, a whole lot of things that I have never used before, and because it's enjoyable. So in this blog post, I would like to share with you the experience, and of course, to show off the [final product](https://khangnd.info/) which I feel so proud and happy to realize how far I have progressed with my skills 😊.

## A little bragging/motivation

Back when I joined DEV community in late October of 2020, I made my entrance by leaving a comment on the 96th Welcome Thread to introduce myself with my portfolio.

{%embed https://dev.to/khangnd/comment/173o9 %}

And it turned out, people enjoyed my portfolio, [the github repo](https://github.com/khang-nd/.info/tree/v1) received around 20⭐, my comment received the most ❤ reactions at that time, and in the end, I was awarded the [Beloved Comment badge](https://dev.to/badge/beloved-comment). Totally unexpected, I was super excited, what an epic entrance I had!

![Davie504 Epico](https://c.tenor.com/wCUmKO7goKcAAAAC/davie504-epic.gif)

But yeah, that's that. Just to say I built the first version of my portfolio nearly 2 years ago, and again, it was not to impress the recruiters as I was already working at my [former company](https://www.bosch.com/), but rather, I was learning React and tried to find something to practice its fundamental concepts. I had no experience with React prior to joining that company, all I knew was HTML, CSS, JS, and some jQuery, just basic stuff huh. React at that time was something foreign, something fancy to me. In fact, even during the whole time I worked at the former company, we rarely needed to build anything that was complex enough to apply any library or framework, other than jQuery, as most of those things we worked on were just automation scripts and simple plugins. But anyhow, we were still allowed the freedom to apply any new library/framework we preferred in our work per our team's competency skills development policies. And that was the motivation for me to build my first portfolio in React.

Now at the new workplace, in the role I have been yearning for, having a chance to build UI stuff from the beautiful designs prepped by a strong and professional design team, I'm really enjoying myself here. However, at the same time, I also feel overwhelmed, due to the fact that those 2 years of experience I had barely fit in the new workplace. I'm now helping build a bigger thing, using more advanced and complex web techs, minding about responsiveness and accessibility while sticking to the designs. All brand new experience to me, which is why I need to keep striving, little by little, and the idea of rewriting my portfolio from scratch using the same tech stack the project is using is part of the effort (FYI, our project is using React/NextJS, TypeScript, Theme UI, Framer Motion for the front-end, Storybook for component documentation, and PostgreSQL as the database, Strapi, Prisma, GraphQL for the back-end, and dozens of other packages). Therefore, for this second incarnation of my portfolio, I applied [NextJS](https://nextjs.org/), [TypeScript](https://www.typescriptlang.org/), [Theme UI](https://theme-ui.com/) and [Framer Motion](https://www.framer.com/motion/).

## The process and experience

[Getting started with NextJS](https://nextjs.org/docs/getting-started) was simple and straightforward, just like any other frameworks whose existence is to ease our life as developers. With just a few commands, I got the all the necessary stuff up and running.

[TypeScript](https://nextjs.org/docs/basic-features/typescript) came integrated with NextJS, I didn't have to worry about anything like the steps to set up or config TS. By enabling the `--ts` flag in the `create-next-app` command, NextJS did all the necessary stuff, simple as that.

Deciding the file/folder structure is probably not a bothersome thing to consider for this kind of project, if not worthless. But still, as someone who prefers things organized and tidy, I did spend quite some time looking up guidelines, best practices and some reference resources. In the end, this is the final structure as of this writing:

![Winport's project structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a8qlqchfpammsoolup5t.png)

For simplicity, the direction I went for was **file separation by types**, React components were placed in the `components` folder, hooks grouped together in the `hooks` folder, contexts in `contexts` and so on. Anything else that didn't make sense to group with the others was dumped in `misc`. The `components` folder was further divided using [Brad Frost's Atomic Design method](https://atomicdesign.bradfrost.com/chapter-2/). I can imagine this is a subjective matter with a never-ending argument when working in a team, as even if it was just me with this project, I still had trouble being firm and decisive and sometimes ended up moving files around. I suppose [**this**](http://react-file-structure.surge.sh/) makes so much sense after experiencing it myself. All in all, my takeaway is that just pick one template/boilerplate of a project with the same type as yours (there are plenty out there) and get right onto it, or don't waste time defending your ideal if it's not a big deal or causes major refactoring. We have 💩 to do, a lot of it.

Working with TypeScript turned out to be surprisingly pleasant. Surprising in a sense that I actually have learned and tried static-typed languages before (Java, C# back in the days I was still in college) and didn't quite like those languages due to their complexity from my **personal** perspective. I grew attached to JavaScript after learning about web dev as it offered the freedom to define and use variables in any way I wanted, I didn't have to worry about what type I should assign or no longer the nightmares of trying to understand the concepts associated to those static types (OOP, polymorphism, abstraction, anyone?). I guess at that point, my brain was not mature enough to accept them as well as the great advantages they bring. As a result, I never expected that I would come back to like static type one day. However, TypeScript changed my mind, the longer I worked with it, the more benefits I could realize and enjoy. There are just way too many benefits that I could easily get obsessed with. But again, this is still my **personal** experience, it may not be the case for everyone, the key takeaway is that, to learn and realize the benefits of something fully and thoroughly, the only way is to see it for yourself, experience it, and feel.

[Theme UI](https://theme-ui.com/getting-started/) was an awesome toy to play the "organized" game. All the styling variables, such as spacings, sizes, colors, breakpoints were centrally defined in [one place](https://github.com/khang-nd/khang-nd.github.io/blob/main/src/themes/index.ts) and they could be used across all our components, making a constraint to enforce the consistency. Even better, the almighty [`sx` prop](https://theme-ui.com/sx-prop) brought a lot of benefits, such as inline styling for our components, and made the pain of coming up with the class names disappear. And as the name implies, Theme UI is perfect for, you know, [theming the UI](https://theme-ui.com/theme-spec), it was designed for that and did that job flawlessly. It supported dark/light mode out of the box and offered the hooks to manipulate the color modes so easily. However, my portfolio was slightly unique in the way that it offered several different themes that didn't simply rely on the color mode, but also on some features of the UI.

| Flat | Soft
|----|----
|![Flat theme](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ksdbpfugmrvygkupy4pc.png) | ![Soft theme](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0n1er1xc5wve7gxms0g2.png)

_The Flat theme has the navigation link in a square shape, while the Soft theme has it mildly rounded with some shadow shades_

To solve this, I made a super simple hook that validated the current theme and use it to style the component correspondingly as below:

```ts
// useMatchTheme
import { useContext } from "react";
import { GlobalContext } from "../contexts/GlobalContext";
import { ThemeMode } from "../themes";

export default function useMatchTheme(target: ThemeMode) {
  const { theme } = useContext(GlobalContext);
  return theme.val === target;
}
```

```ts
// NavLink.tsx
const linkStyle: ThemeUICSSObject = {
    bg: "primary",
    color: "textReverse",
    display: "flex",
    // some more styles here

    ...(useMatchTheme(ThemeMode.Soft) && {
      fontSize: isHomePage ? "2px" : "1px",
      borderRadius: "10%",
      boxShadow: (theme) => `inset 3em 3em 3em rgba(255, 255, 255, 0.5), 1em 1em 4em 3em ${theme.colors?.shadow}`,
    }),

    ...(useMatchTheme(ThemeMode.Classic) && {
      fontSize: isHomePage ? "2px" : "1px",
      borderRadius: "8%",
      boxShadow: "inset 0 0 0 2em #000, 3em 3em 0 #000",
    }),
  };
```

[Framer Motion](https://www.framer.com/docs/introduction/) was another animation library designed specifically for React and it did it job really well. It was a little tough to get a hang onto at the beginning since I had little experience with React and literally zero experience with any animation library. But once I got a hang of it, I absolutely loved it. The animations are super clean and realistic, I guess it was thanks to these so-called spring and bouncing physics (don't talk to me so deep into Math 😢). The API was simple to use as well as the good documentation with practical examples. (Staring at the old animations in my old porfolio, so fkn 💩). What made Framer Motion even more extreme, from my experience, were these [Layout animation](https://www.framer.com/docs/animation/#layout-animations) which manipulated the animations on components as if they transitioned from one position to another, and [AnimatePresence component](https://www.framer.com/docs/animate-presence/) which allows animations on components as they were removed from the React tree.

![Magic](https://i.pinimg.com/originals/73/e5/53/73e55358e7b0703f20602b01b408e9e6.gif)

As the goal at the beginning was simply to apply a different tech stack to rebuild my portfolio and learn a thing or two out of it, I didn't want to deviate much from the existing core design, but in the end, I felt that there could have been a lot of improvements from the old version, so I think it's interesting to share the look of those differences:

| Old | New
|---  | ---
|![Flat old](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c5setkk5r8vv0a827831.png) | ![Flat new](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yb0i052968qmo2oisypo.png)
|![Neumorphism old](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4casxddwzs04npx47pw3.png) |![Soft new](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yex2z4g3cjhlku1wx5mv.png)
|![Classic old](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zo3od84unipobzchv55p.png)|![Classic new](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n084yvdvii1ehccb0mdo.png)
|![Old config panel](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qaaexff0c1961udu1pf1.png)|![New config panel](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/itsuny7wcj9wj52kjnwu.png)

Aside from the improvements on how it looked. There were a couple of other improvements behind the scene, including accessibility, new config options (hide taskbar, reduce motion), hiding the config panel on unfocused, and an entire Blog section which pulls the article lists from my contributed blogging platforms using their public APIs.

## Final words

I've got a confession to make. All of this blog was just to _brag_ about my new portfolio, to make a big fuss out of it as I invested a lot of my spare time doing it 😋 But I still hope it's  helpful and somehow serves as an inspiration for your new portfolio or your next one. Thank you for reading.

* [Old version of my portfolio](https://web.archive.org/web/20220509014455/https://khang-nd.github.io/) ([source code](https://github.com/khang-nd/.info/tree/v1))
* [New version of my portfolio](https://khangnd.info/) ([source code](https://github.com/khang-nd/.info/))