<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mangor1no</title>
    <description>The latest articles on DEV Community by Mangor1no (@mangor1no).</description>
    <link>https://dev.to/mangor1no</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F521595%2F7ab641a4-8cac-40cd-ab7a-823b76ef73f9.png</url>
      <title>DEV Community: Mangor1no</title>
      <link>https://dev.to/mangor1no</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mangor1no"/>
    <language>en</language>
    <item>
      <title>How I crafted my own portfolio and put it on the Internet</title>
      <dc:creator>Mangor1no</dc:creator>
      <pubDate>Mon, 10 Oct 2022 14:39:23 +0000</pubDate>
      <link>https://dev.to/mangor1no/how-i-crafted-my-own-portfolio-and-put-it-on-the-internet-bp7</link>
      <guid>https://dev.to/mangor1no/how-i-crafted-my-own-portfolio-and-put-it-on-the-internet-bp7</guid>
      <description>&lt;h2&gt;
  
  
  Hello there 👋
&lt;/h2&gt;

&lt;p&gt;This is the first time ever I post anything on &lt;a href="https://www.dev.to"&gt;Dev.to&lt;/a&gt;. I've been lurking in the shadow, reading all kind of interesting posts here and finally I think it's time to write my own post to contribute something to the forum.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z0tz_5EG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hvmwqb0r7pm0a94zbx5s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z0tz_5EG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hvmwqb0r7pm0a94zbx5s.png" alt="Me reading the comments from posts on dev.to" width="600" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What I planned was to create my own portfolio and put it on the internet, so HR and other developers can find me easily. Howerver, since I was &lt;del&gt;lazy&lt;/del&gt; busy at work, it stayed on my backlog for a long time. Until last week, I finally decided to start working on it after reading &lt;a href="https://dev.to/naomipham_/how-to-create-darklight-mode-with-react-and-tailwind-59e0"&gt;this nice article&lt;/a&gt; on the forum. Shout out to &lt;strong&gt;Naomi&lt;/strong&gt; for the motivation and inspiration.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I choose techs for my portfolio 👀
&lt;/h2&gt;

&lt;p&gt;I decided to start working on the portfolio with my most favourited framework: &lt;a href="https://nextjs.org/"&gt;NextJS&lt;/a&gt;. The reason why I chose NextJS instead of writing my portfolio using normal React is &lt;a href="https://blog.logrocket.com/how-next-js-can-help-improve-seo/"&gt;the ability to SEO&lt;/a&gt;. Also since I kinda hate to do the routing in React using &lt;code&gt;react-router-dom&lt;/code&gt;, NextJS routing system is my go-to. For now, my portfolio only have one route, but I'm planning to add a new blog page to my website, so it's better to get prepared first. &lt;/p&gt;

&lt;p&gt;Also, let's not forget about &lt;a href="https://tailwindcss.com/"&gt;TailwindCSS&lt;/a&gt;. The first time I used it, I felt in love with the library almost immediatetly. TailwindCSS helps me to create a very well-structured CSS in the codebase, and I'm using it in almost every projects I'm working on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps to make my dream portfolio comes true
&lt;/h2&gt;

&lt;p&gt;Let's get started by running the command to create the initial project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn create next-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D8bmSaQc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4l8ke9qdg7uruyzlyaid.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D8bmSaQc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4l8ke9qdg7uruyzlyaid.png" alt="Project initiation" width="880" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By default, NextJS will come with &lt;code&gt;eslint&lt;/code&gt; pre-installed. I will add another library called &lt;code&gt;prettier&lt;/code&gt; and use it along with &lt;code&gt;eslint&lt;/code&gt; to control my code's quality. Also, I install a plugin called &lt;code&gt;prettier-plugin-tailwindcss&lt;/code&gt; to auto sort my TailwindCSS classes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add --dev prettier eslint-config-prettier prettier-plugin-tailwindcss
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This step here is my own preference, you can skip it or follow it. But I think it's always good to have a barrier preventing you from falling into the abyss. &lt;br&gt;
My Prettier and ESlint configuration will look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IPP6M1Dv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o4d1x093sdaswig3nuar.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IPP6M1Dv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o4d1x093sdaswig3nuar.png" alt="Prettier" width="540" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WEHrtS5t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y0noiz982ijx1tv6n049.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WEHrtS5t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y0noiz982ijx1tv6n049.png" alt="ESlint" width="717" height="944"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next step we need to install TailwindCSS. More commands 👀&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add --dev tailwindcss postcss autoprefixer
npx tailwindcss init -p
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first command will add the library into &lt;code&gt;devDependencies&lt;/code&gt; inside your &lt;code&gt;package.json&lt;/code&gt; file. You can check out the different between &lt;code&gt;dependencies&lt;/code&gt; and &lt;code&gt;devDependencies&lt;/code&gt; &lt;a href="https://docs.npmjs.com/specifying-dependencies-and-devdependencies-in-a-package-json-file"&gt;here&lt;/a&gt;. The second command will create 2 files: &lt;code&gt;tailwind.config.js&lt;/code&gt; and &lt;code&gt;postcss.config.js&lt;/code&gt;. We need to add some lines of code into &lt;code&gt;tailwind.config.js&lt;/code&gt; file and import &lt;code&gt;@tailwind&lt;/code&gt; directive into the global css file to make it works.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6412LOA2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4cukxpy7dryjpmf46ec2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6412LOA2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4cukxpy7dryjpmf46ec2.png" alt="Tailwind setup" width="880" height="603"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, I will add property &lt;code&gt;darkMode: 'class'&lt;/code&gt; into &lt;code&gt;tailwind.config.js&lt;/code&gt; to control my portfolio's dark mode using classes.&lt;/p&gt;

&lt;p&gt;Let's talk about the font. I found that the font &lt;strong&gt;Inter&lt;/strong&gt; looks attractive and clear, so I used it as the main font for my portfolio. Let's open google font and grab the font we need, created a file called &lt;code&gt;_document.js&lt;/code&gt; inside our project and put the tags into our file.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--149Hom31--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e4dq2jxpi4zi8gfm13p4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--149Hom31--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e4dq2jxpi4zi8gfm13p4.png" alt="Google Font" width="880" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TEiKgL8T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cct32etz15dnz0t66ca2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TEiKgL8T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cct32etz15dnz0t66ca2.png" alt="_document.js file" width="880" height="527"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, we can setup the absolute import function for our project to prevent ugly &lt;code&gt;../../../../components/OurNiceComponent.js&lt;/code&gt; thingy. Luckily, NextJS starts automatically support &lt;code&gt;jsconfig.json&lt;/code&gt; "paths" and "baseUrl" options since Next.js 9.4, so we just need to create a new file called &lt;code&gt;jsconfig.js&lt;/code&gt;, add the configuration like this and it will work nicely.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vR9iNukG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i8rv8mwyjtdr9airima4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vR9iNukG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i8rv8mwyjtdr9airima4.png" alt="Absolute import" width="574" height="167"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The result after we have absolute import working&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Uau1VUsq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vcr1zfs1wqqea4sa01ix.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Uau1VUsq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vcr1zfs1wqqea4sa01ix.png" alt="Absolute import result" width="880" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This looks much nicer in general, isn't it? &lt;/p&gt;

&lt;p&gt;Now, we start coding. I won't dive too deep in my codebase, since you can check it out in &lt;a href="https://github.com/Mangor1no/russ-portfolio"&gt;my Github repo&lt;/a&gt;. However, I do have some points that I found they are quite interesting, and will share with you guys how I handled them.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Flash of unstyled content&lt;/li&gt;
&lt;li&gt;Website optimization&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Flash of unstyled content
&lt;/h2&gt;

&lt;p&gt;The most important thing you need to do when setup dark mode for your website is to keep the theme selected by the user. Normally, you can save a key to localStorage to identify the selected theme.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;darkMode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setDarkMode&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initDarkMode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isDarkMode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your-theme&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isDarkMode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setDarkMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setDarkMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;initDarkMode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;changeThemeHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;setDarkMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;setDarkMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your-theme&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;darkMode&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;changeThemeHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;changeThemeHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;Change&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code block above will help you to set the theme base on the value of the key &lt;code&gt;your-theme&lt;/code&gt; in localStorage. However, when you refresh the browser, you will start notice a problem: Your website will flash a white screen before it changes to dark theme. This problem happens because the function &lt;code&gt;initDarkMode()&lt;/code&gt; is being placed inside &lt;code&gt;useEffect()&lt;/code&gt;, which runs after the content has been rendered.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7A6CZ8NX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g7wn0h34yyh24gtv8e3o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7A6CZ8NX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g7wn0h34yyh24gtv8e3o.png" alt="useEffect timing" width="803" height="197"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The solution for this problem is quite simple. Open the file &lt;code&gt;_document.js&lt;/code&gt; and add the script below inside the &lt;code&gt;&amp;lt;Head /&amp;gt;&lt;/code&gt; tags.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;
  &lt;span class="nx"&gt;dangerouslySetInnerHTML&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
    &lt;span class="na"&gt;__html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
      (function () {
        const themeKey = 'your-theme';
        const classNameDark = 'dark';
        const classNameLight = 'light';

        function setClassThemeOnDocumentBody(darkMode) {
          if (darkMode === 'dark') {
            document.documentElement.classList.add(classNameDark);
          } else {
            document.documentElement.classList.remove(classNameDark);
          }
        }
          let localStorageTheme = null;
          try {
            localStorageTheme = localStorage.getItem(themeKey);
          } catch (err) {}
          const localStorageExistsTheme = localStorageTheme !== null;

          // Determine the source of truth
          if (localStorageExistsTheme) {
            // source of truth from localStorage
            setClassThemeOnDocumentBody(localStorageTheme);
          } else {
            // default theme is light theme
            localStorage.setItem(themeKey, 'light');
          }
      }());
    `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}}&lt;/span&gt;
&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By adding this small script, we are able to block the browser rendering and set the theme before browser paints our page. No more flashing 👌.&lt;/p&gt;

&lt;h2&gt;
  
  
  Website optimization
&lt;/h2&gt;

&lt;p&gt;There are plenty of ways to check how optimized your website are, but my favourite way is using &lt;a href="https://web.dev/measure"&gt;Google Audit&lt;/a&gt;. The tool will give you an insight about your website, including website's Performance, Accessibility, Best Pratice and SEO. On my first audit, the performance score for my portfolio was 84, which was kinda bad for a simple page.&lt;/p&gt;

&lt;p&gt;The first thing I did is to compress my images. But since my portfolio only have one image, there was no significant change. Back to the audit report, I noticed that my First Contentful Paint (FCP) time was long, and the tool said I should avoid chaining critical requests. A little bit more inspection and I found out that the font size downloaded from Google Font is too large. In fact, the requests size for this font was more than 136kB per font type, added up to more than 340kB in total!&lt;/p&gt;

&lt;p&gt;As every normal developers, I started begging Google for help. I bumped into &lt;a href="https://www.labnol.org/internet/reduce-google-fonts-size/21057/"&gt;this article&lt;/a&gt;, and after applied this method to my portfolio.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;
  &lt;span class="nx"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;preload&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800&amp;amp;display=swap&amp;amp;text=1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM%22%27%28%29%2C%2D%2E%3A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;
  &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800&amp;amp;display=swap&amp;amp;text=1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM%22%27%28%29%2C%2D%2E%3A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="nx"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stylesheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By adding &lt;code&gt;text&lt;/code&gt; query to the url and use only needed characters for the font, my total requests size for the font was less than 40kB in total. It means I have reduced nearly 90% of requests size. Stunning result! 😳&lt;/p&gt;

&lt;p&gt;Here is my portfolio audit score after the optimization: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Lz3Cup_x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c8zwi95acrvrg4pugfbq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Lz3Cup_x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c8zwi95acrvrg4pugfbq.png" alt="Final result" width="880" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Put the portfolio on the Internet
&lt;/h2&gt;

&lt;p&gt;I bought a cheap domain and used Vercel to host my portfolio. The integration was quite easy and fast, I just updated the CNAME and IP Address of Vercel to my domain and it did the rest of the works for me. Thanks Vercel for bringing such an amazing deployment experience to the developers!&lt;/p&gt;

&lt;h2&gt;
  
  
  Final words
&lt;/h2&gt;

&lt;p&gt;Thank you for spending time to read my long article 🙇‍♂️.&lt;/p&gt;

&lt;p&gt;You can checkout my portfolio &lt;a href="https://www.russdev.net"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to find the codes, please checkout my &lt;a href="https://github.com/Mangor1no/russ-portfolio"&gt;Github repository&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>nextjs</category>
      <category>career</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
