Building my portfolio website using Next js, Framer Motion, TypeScript, Tailwind CSS

Building my portfolio website using Next js, Framer Motion, TypeScript, Tailwind CSS

ยท

6 min read

This article is about the code used to build my portfolio project.

1. Setup

npx create-next-app@latest

npx create-next-app@latest . to install in the current directory.

to run server

npm run dev

To remove the favicon.ico:

  • stop the server using ctrl + c and type 'y' in the vscode terminal.

  • delete the .next folder

  • now start the server using the cmd npm run dev, the .next folder will be created automatically.

to check whether you have tailwind css installed or not: npm view tailwindcss version

absolute will take the div out of its flow.

CSS code for the bg blur:

<div className="bg-[#fbe2e3] absolute top-[-6rem] -z-10 right-[11rem] h-[31.25rem] w-[31.25rem] rounded-full blur-[10rem] sm:w-[68.75rem] dark:bg-[#946263]"></div>
<div className="bg-[#dbd7fb] absolute top-[-1rem] -z-10 left-[-35rem] h-[31.25rem] w-[50rem] rounded-full blur-[10rem] sm:w-[68.75rem] md:left-[-33rem] lg:left-[-28rem] xl:left-[-15rem] 2xl:left-[-5rem] dark:bg-[#676394]"></div>

create a lib folder ๐Ÿ“‚.

create a data.ts file in the lib folder ๐Ÿ“‚.

paste the entire code in the data.ts file:

import React from "react";
import { CgWorkAlt } from "react-icons/cg";
import { FaReact } from "react-icons/fa";
import { LuGraduationCap } from "react-icons/lu";
import corpcommentImg from "@/public/corpcomment.png";
import rmtdevImg from "@/public/rmtdev.png";
import wordanalyticsImg from "@/public/wordanalytics.png";

export const links = [
  {
    name: "Home",
    hash: "#home",
  },
  {
    name: "About",
    hash: "#about",
  },
  {
    name: "Projects",
    hash: "#projects",
  },
  {
    name: "Skills",
    hash: "#skills",
  },
  {
    name: "Experience",
    hash: "#experience",
  },
  {
    name: "Contact",
    hash: "#contact",
  },
] as const;

export const experiencesData = [
  {
    title: "Graduated bootcamp",
    location: "Miami, FL",
    description:
      "I graduated after 6 months of studying. I immediately found a job as a front-end developer.",
    icon: React.createElement(LuGraduationCap),
    date: "2019",
  },
  {
    title: "Front-End Developer",
    location: "Orlando, FL",
    description:
      "I worked as a front-end developer for 2 years in 1 job and 1 year in another job. I also upskilled to the full stack.",
    icon: React.createElement(CgWorkAlt),
    date: "2019 - 2021",
  },
  {
    title: "Full-Stack Developer",
    location: "Houston, TX",
    description:
      "I'm now a full-stack developer working as a freelancer. My stack includes React, Next.js, TypeScript, Tailwind, Prisma and MongoDB. I'm open to full-time opportunities.",
    icon: React.createElement(FaReact),
    date: "2021 - present",
  },
] as const;

export const projectsData = [
  {
    title: "CorpComment",
    description:
      "I worked as a full-stack developer on this startup project for 2 years. Users can give public feedback to companies.",
    tags: ["React", "Next.js", "MongoDB", "Tailwind", "Prisma"],
    imageUrl: corpcommentImg,
  },
  {
    title: "rmtDev",
    description:
      "Job board for remote developer jobs. I was the front-end developer. It has features like filtering, sorting and pagination.",
    tags: ["React", "TypeScript", "Next.js", "Tailwind", "Redux"],
    imageUrl: rmtdevImg,
  },
  {
    title: "Word Analytics",
    description:
      "A public web app for quick analytics on text. It shows word count, character count and social media post limits.",
    tags: ["React", "Next.js", "SQL", "Tailwind", "Framer"],
    imageUrl: wordanalyticsImg,
  },
] as const;

export const skillsData = [
  "HTML",
  "CSS",
  "JavaScript",
  "TypeScript",
  "React",
  "Next.js",
  "Node.js",
  "Git",
  "Tailwind",
  "Prisma",
  "MongoDB",
  "Redux",
  "GraphQL",
  "Apollo",
  "Express",
  "PostgreSQL",
  "Python",
  "Django",
  "Framer Motion",
] as const;

To use an SVG file in your React project, you can import it and then use it as a component. Here's how you can do it:

import using @@ ,

 "paths": {
      "@/*": ["./src/*"],
      "@@/*": ["./*"]
    }

then use the varibale.

icon: GraduateCap,

2. Header

create components folder ๐Ÿ“‚

create header.tsx file.

install es7 + extension for boilerplates.

use rfc

install framer motion:

npm install framer-motion

"use client"; to tell header.tsx file is a client component.

<header className="z-[999] relative">
  <motion.div
    className="fixed top-0 left-1/2 h-[4.5rem] w-full rounded-none border border-white border-opacity-40 bg-white bg-opacity-80 shadow-lg shadow-black/[0.03] backdrop-blur-[0.5rem] sm:top-6 sm:h-[3.25rem] sm:w-[36rem] sm:rounded-full dark:bg-gray-950 dark:border-black/40 dark:bg-opacity-75"
    initial={{ y: -100, x: "-50%", opacity: 0 }}
    animate={{ y: 0, x: "-50%", opacity: 1 }}
  ></motion.div>

  <nav className="flex fixed top-[0.15rem] left-1/2 h-12 -translate-x-1/2 py-2 sm:top-[1.7rem] sm:h-[initial] sm:py-0">
    <ul className="flex w-[22rem] flex-wrap items-center justify-center gap-y-1 text-[0.9rem] font-medium text-gray-500 sm:w-[initial] sm:flex-nowrap sm:gap-5">
      {links.map((link) => (
        <motion.li
          className="h-3/4 flex items-center justify-center relative"
          key={link.hash}
          initial={{ y: -100, opacity: 0 }}
          animate={{ y: 0, opacity: 1 }}
        >
          <Link
            className={
              "flex w-full items-center justify-center px-3 py-3 hover:text-gray-950 transition dark:text-gray-500 dark:hover:text-gray-300"
            }
            href={link.hash}
          >
            {link.name}
          </Link>
        </motion.li>
      ))}
    </ul>
  </nav>
</header>

3. Intro section

create intro.tsx file in components folder ๐Ÿ“‚

Everything belongs to same semantic meaning than using section.

In the page.tsx:

add the intro and place the cursor and hit: ctrl + spacebar and select the intro.tsx file to import into page.tsx.

modify next config mjs file to include the external image.

Extend eslintrc json to remove the apos syntax errors rules

{
  "extends": "next/core-web-vitals",
  "rules": {
    "react/no-unescaped-entities": 0
  }
}

to use svg files

i have used image tag.

install

npm install @react-spring/web

4. Section divider

create section-divider file.

"use client";

import React from "react";

export default function SectionDivider() {
  return (
    <div
      className="bg-gray-200 my-24 h-16 w-1 rounded-full hidden sm:block dark:bg-opacity-20"
    ></div>
  );
}

add to page.tsx

Using rough notation library

npm install --save react-rough-notation

5. About section

create about.tsx file

use rfc

create a file section-heading.tsx

6. Projects section

create projects.tsx file

create project.tsx file

7. Finish header

using scroll property to scroll to the sections.

adding smooth scroll for all the layout.

keeping track of active section using state.

install clsx framework to apply classes conditionally

npm install --save clsx

conditionally applying background color

{
    link.name === activeSection && (
        <motion.span
            className="bg-gray-100 rounded-full absolute inset-0 -z-10 dark:bg-gray-800"
            layoutId="activeSection"
            transition={{
                type: "spring",
                stiffness: 380,
                damping: 30,
            }}
        ></motion.span>
    )
}

using onclick:

 onClick={() => {
                  setActiveSection(link.name);
                  setTimeOfLastClick(Date.now());
                }}

as you scroll the active session should change the background not only when you click:

intersection observer API in react intersection observer

npm install react-intersection-observer --save

create context folder and create active-section-context.tsx file

create hook.ts file in lib folder ๐Ÿ“‚

create types.ts file in lib folder ๐Ÿ“‚

8. Skills section

create a skills.tsx file

9. Experience section

create experience.tsx file

npm i react-vertical-timeline-component

types declaration package

npm i --save-dev @types/react-vertical-timeline-component

create theme-context.tsx file

Error:

  • Server Error Error: Cannot read properties of undefined (reading 'prototype')

    • "use client";

10. Contact section

create contact.tsx file

toast

npm install react-hot-toast

create email folder and contact-form-email.tsx file

npm i @react-email/components

create actions folder ๐Ÿ“‚ and sendEmail.ts file:

create utils.ts file in lib folder

create submit-btn.tsx file in component folder

improved:

11. Footer

create footer.tsx file

added functionality to let user like

adding error checks

Final:

Conclusion

Learning Objectives,

  1. Setup using next js,

  2. Project setup.

  3. Installing dependencies,

  4. using scroll property to scroll to the sections.

  5. implemented toast libs.

  6. Implemented predefined text messages.

  7. Added functionality to like

  8. Added error checks

Source: ByteGrad YT [Link], [Link]

Author: Dheeraj. Yss

Connect with me:

Did you find this article valuable?

Support dheerajy blog by becoming a sponsor. Any amount is appreciated!

ย