Every developer must have a portfolio website to showoff their skills and projects.
If you prefer video tutorial you can watch it here:
In this article I’ll show you how to do exactly that.
We will build portfolio website with React.js and Tailwind CSS.
You may ask It's just a landing page?
Why not build it with vanilla CSS and Html.
The reason I choose React and Tailwind to build this project is because I’ll integrate a blog API into this project. I’ll share that in a future article.
Prerequisite:
To follow along you don’t need to be a pro at anything, all you need is just the fundamentals.
- Basic understanding of vanilla CSS
- Basic understanding of JavaScript.
- Fundamental of React and Tailwind.
Now that you know what you need, let’s start building.
Setup
To build the project first we need to setup a React.js and Tailwind CSS project. You can do that easily using the Tailwind docs.
Follow these instructions from tailwind docs to setup the project.
Setup React and Tailwind Project
I’ll wait for you to setup the project.
You are done!
let’s move on to the next step.
The Components
Before we start we need to know little about the structure of the project.
Because it’s React we will be breaking down the websites into tiny components.
We’ll have 6 components:
- Header
- Hero
- About
- Projects
- Blog
- Footer
Note: all these components will be inside the components folder under the src folder. And all the component will be imported in the App.js file.
Like this:
import "./App.css";
import Header from "./components/Header";
import Hero from "./components/Hero";
import About from "./components/About";
import Projects from "./components/Projects";
import Blog from "./components/Blog";
import Contact from "./components/Contact";
import Footer from "./components/Footer";
function App() {
return (
<>
<Header />
<Hero />
<About />
<Projects />
<Blog />
<Contact />
<Footer />
</>
);
}
export default App;
#1. Header
The have a responsive mobile menu with a toggle button, and a desktop menu.
We will use react useState hook to implement the toggle effect. And for the icons we’ll use the React Icons library.
import React, { useState } from "react";
import { AiOutlineMenu, AiOutlineClose } from "react-icons/ai";
const Header = () => {
const [toggle, setToggle] = useState(false);
const handleToggle = () => setToggle(!toggle);
return (
<header className="flex justify-between px-5 py-2 bg-primary text-white fixed w-full z-10">
<a href="/" className="logo text-2xl font-bold text-accent">
Amrin
</a>
{/* Desktop Nav */}
<nav className="hidden md:block">
<ul className="flex">
<li>
<a href="/#about">About</a>
</li>
<li>
<a href="/#projects">Projects</a>
</li>
<li>
<a href="/#blog">Blog</a>
</li>
<li>
<a href="/#contact">Contact</a>
</li>
<li>
<a href="#resume -link" target="_blank" without rel="noreferrer">
Resume
</a>
</li>
</ul>
</nav>
{/* Mobile Nav */}
<nav
className={!toggle ? "mobile-nav left-[-100%]" : "mobile-nav left-0"}
>
<ul className="flex flex-col">
<li>
<a href="/#about">About</a>
</li>
<li>
<a href="/#projects">Projects</a>
</li>
<li>
<a href="/#blog">Blog</a>
</li>
<li>
<a href="/#contact">Contact</a>
</li>
<li>
<a href="/#resume">Resume</a>
</li>
</ul>
</nav>
{/* Toggle button */}
<button onClick={handleToggle} className="block md:hidden">
{!toggle ? <AiOutlineMenu size={30} /> : <AiOutlineClose size={30} />}
</button>
</header>
);
};
export default Header;
Because we have a custom color pallet, I decided to create some utility classes for the colors.
/* color */
.bg-primary {
background: #0F172A;
}
.bg-secondery {
background: #1E293B;
}
.bg-accent {
background: #7477FF;
}
.text-accent {
color: #7477FF;
}
As we styled the mobile nav with tailwind, it was getting really messy and repetitive. So, I decided to extract the classes and put them on a custom class called .mobile-nav on Style.css file, like this
.mobile-nav {
@apply block md:hidden fixed top-10 py-2 w-full h-full bg-gray-900 duration-500;
}
Also to style the a tags inside nav, we used some custom css. Otherwise we would repeat ourselves a lot.
nav li a {
@apply px-4 py-5 text-lg;
}
nav li a:hover {
color: #7477FF;
}
Now that we are done with the nav let’s move on to the hero section.
#2. Hero
The hero consists of two sections, one is the hero-info and the other is hero-img.
I’ve used an illustration on the hero-img you can use your picture if you prefer.
import React from "react";
import HeroImg from "../assets/hero-img.png";
import {
AiOutlineTwitter,
AiOutlineYoutube,
AiOutlineFacebook,
} from "react-icons/ai";
const Hero = () => {
return (
<section className="bg-primary px-5 text-white py-32">
<div className="container mx-auto grid md:grid-cols-2 items-center justify-center md:justify-between">
<div className="hero-info pb-5 md:pb-0">
<h1 className="text-4xl lg:text-6xl">
Hi, <br />I am <span className="text-accent">a</span>mrin <br />
Frontend Developer
</h1>
<p className="py-5">
I am proficient in JavaScript, React.js and Tailwind CSS
</p>
<div className="flex py-5 ">
<a
href="https://twitter.com/CoderAmrin"
className="pr-4 inline-block text-accent hover:text-white"
>
{" "}
<AiOutlineTwitter size={40} />{" "}
</a>
<a
href="https://www.youtube.com/@coderamrin"
className="pr-4 inline-block text-accent hover:text-white"
>
{" "}
<AiOutlineYoutube size={40} />{" "}
</a>
<a
href="https://www.facebook.com/CoderAmrin/"
className="pr-4 inline-block text-accent hover:text-white"
>
{" "}
<AiOutlineFacebook size={40} />{" "}
</a>
</div>
<a
href="/#projects"
className=" btn bg-accent border-2 border-[#7477FF] text-white px-6 py-3 hover:bg-transparent"
>
See Projects
</a>
</div>
<div className="hero-img">
<img
src={HeroImg}
alt="coding illustration"
className="lgw-[80%] ml-auto"
/>
</div>
</div>
</section>
);
};
export default Hero;
To style the hero title, we’ve used a custom font and added some custom styling.
Note: you’ll need to add this font on the index.html of your project. It’s a free google font.
/* hero */
h1 {
font-family: 'Pacifico', cursive;
line-height: 1.5 !important;
}
#3. About
The about section consists of two parts just like the hero section.
First section will have all about you, what skills you have and what do you do. And the other section is about-img. It’s an illustration of a person coding.
Note: All the images are in the src/assets directory.
import React from "react";
import AboutImg from "../assets/about-img.png";
const About = () => {
return (
<section className="bg-secondery text-white px-5 py-32" id="about">
<div className="container mx-auto grid md:grid-cols-2 items-center justify-center md:justify-between">
<div className="about-info">
<h2 className="text-4xl font-bold mb-5 border-b-[5px] w-[180px] border-indigo-600 pb-2">
About Me
</h2>
<p className="pb-5">
Hi, My Name Is Rohima Akther everyone calls me Amrin. I am a
Frontend Developer. I build beautifull websites with React and
Tailwind CSS.
</p>
<p className="pb-5">
I am proficient in Frontend skills like React.js, Redux, Redux Tool
Kit, Axios, Tailwind CSS, SaSS, Css3 and many more.
</p>
<p>In backend I know Node.js, Express.js, MongoDB, and Mongoose</p>
<p>
In my spare time I create YouTube videos and write blogs on my Blog.
Where I talk about programming theory and build various projects.
</p>
</div>
<div className="about-img">
<img
src={AboutImg}
alt="coding illustration"
className="lgw-[80%] md:ml-auto"
/>
</div>
</div>
</section>
);
};
export default About;
To style this section we haven’t used any other custom css other than the color classes.
#4. Project
The project section is a little bit complex. First we’ve got all the projects in an array, so that we don’t have to repeat ourselves. With this array of projects we now can easily map through and render the project item.
const projects = [
{
img: devlog,
title: "devlog",
desc: " A multi author blog. Built with Node.js, MongoDB, React, Redux and Tailwind CSS ",
live: "https://devlogg.onrender.com/",
code: "https://github.com/Coderamrin/devlog",
},
{
img: uilogs,
title: "uilogs",
desc: "Free website template directory for SaaS and Degital Agency. Built with Bootstrap, JQuery and JavaScript",
live: "https://uilogs.xyz/",
code: "https://github.com/Coderamrin/html-templates",
},
{
img: cssProjects,
title: "css projects",
desc: "Frontend Mentor challange directory, solved with vanilla CSS",
live: "https://build-10-css-projects.netlify.app/",
code: "https://github.com/Coderamrin/build-10-css-projects",
},
{
img: getInspirred,
title: "get Inspirred",
desc: "Quote search app. Used Quotable API for the quotes and React, Redux on the frontend",
live: "https://get-inspirred.netlify.app/",
code: "https://github.com/Coderamrin/get-inspired",
},
];
The rest of the product component is this.
import React from "react";
import cssProjects from "../assets/cssprojects.png";
import devlog from "../assets/devlog.png";
import getInspirred from "../assets/get-inspirred.png";
import uilogs from "../assets/uilogs.png";
const Projects = () => {
const projects = [...];
return (
<section className="bg-primary text-white px-5 py-32" id="projects">
<div className="container mx-auto grid md:grid-cols-2 items-center md:justify-between">
<div className="about-info mb-5">
<h2 className="text-4xl font-bold mb-5 border-b-[5px] w-[180px] border-indigo-600 pb-2">
Projects
</h2>
<p className="pb-5">
These are some of my best projects. I have built these with React,
MERN and vanilla CSS. Check them out.
</p>
</div>
<div className="about-img"></div>
</div>
<div className="projects container mx-auto grid md:grid-cols-3 gap-10">
{projects.map((project, i) => {
return (
<div className="relative" key={i}>
<img src={project.img} alt={project.title} />
<div className="flex absolute left-0 right-0 top-[13px] bottom-0 mx-auto w-[90%] h-[90%] bg-primary opacity-0 duration-500 justify-center flex-col hover:opacity-100 ">
<p className="py-5 text-center font-bold px-2 text-white">
{project.desc}
</p>
<div className="mx-auto">
<a
href={project.live}
className="px-5 py-2 bg-blue-500 hover:bg-blue-600 mr-5 font-bold"
>
Live
</a>
<a
href={project.code}
className="px-5 py-2 bg-blue-700 hover:bg-blue-800 font-bold"
>
Code
</a>
</div>
</div>
</div>
);
})}
</div>
</section>
);
};
export default Projects;
#5. Blog
Now is the blog section. It almost like the projects section.
An array of blog items to map through and render the items.
All the other things are the same as the projects component.
import React from "react";
const Blog = () => {
const post = [
{
img: "https://res.cloudinary.com/practicaldev/image/fetch/s--AuZFJnr6--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a8okx5rxzuh5fojibsy3.png",
title: "How to build a counter app with JavaScript",
url: "https://dev.to/coderamrin/how-to-build-a-counter-app-with-javascript-439p",
},
{
img: "https://res.cloudinary.com/practicaldev/image/fetch/s--FsJZ6lhI--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gv7y2de8kalk9l0820ag.jpg",
title: "JavaScript Ultimate Guide 02: The DOM",
url: "https://dev.to/coderamrin/javascript-ultimate-guide-02-the-dom-3ho9",
},
];
return (
<section className="bg-primary text-white px-5 py-32" id="blog">
<div className="container mx-auto grid md:grid-cols-2 items-center md:justify-between">
<div className="about-info mb-5">
<h2 className="text-4xl font-bold mb-5 border-b-[5px] w-[100px] border-indigo-600 pb-2">
Blogs
</h2>
<p className="pb-5">Some of my best blogs.</p>
</div>
<div></div>
</div>
<div className="projects container mx-auto grid md:grid-cols-2 gap-10">
{post.map((item) => {
return (
<div>
<img src={item.img} alt={item.title} />
<h3 className="py-5 text-2xl">{item.title}</h3>
<a
href={item.url}
className=" btn bg-accent border-2 border-[#7477FF] text-white px-6 py-3 hover:bg-transparent"
>
Read More
</a>
</div>
);
})}
</div>
</section>
);
};
export default Blog;
#6. Contact & Footer
Finally the contact section and the Footer section.
These sections are just some texts on the center of the div. No, fancy design.
#Contact
import React from "react";
const Contact = () => {
return (
<section className="bg-secondery px-5 py-32" id="contact">
<div className="text-center md:w-[60%] mx-auto text-white">
<h2 className="text-4xl font-bold mb-5 border-b-[5px] w-[200px] mx-auto border-indigo-600 pb-2">
Contact Me
</h2>
<p>
I am currently open for a fulltime Frontend Developer role. If you
want to discuss about that feel free to email me or call me.
</p>
<p className="py-2">
<span className="font-bold">Email:</span> coderamrin@gmail.com
</p>
<p className="py-2">
<span className="font-bold">Phone:</span> +88 01624-890723
</p>
</div>
</section>
);
};
export default Contact;
#Footer
import React from "react";
const Footer = () => {
return <div className="py-4 text-center bg-primary text-white "> © 2023 coderamrin all right reserved</div>;
};
export default Footer;
Resources
Live: https://amrin.onrender.com/
Source Code: https://github.com/Coderamrin/portfolio
Conclusion
Now you have a portfolio. You can deploy it and show off your projects.
If you want you can add a blog to your portfolio and showoff your skills.
I’ll add dev api on this portfolio, if you want to see do the same follow me to notified when I post the article.
If you want to connect with me, you can find me at on Twitter and YouTube.
Thanks for reading to the end.
See you on a future article.
Top comments (17)
In reality, this simply isn't true. I've never had one, and all the best developers I've hired haven't had one. An interesting and active GitHub/GitLab/whatever account is a far better way to attract the interest of the hiring manager. A curated vanity project honestly tells them very little about the candidate. I've rejected a good number of candidates actually because of their portfolio sites. A portfolio site can catch the eye - sure, but if the hirer is doing their job correctly they will look past it for more honest detail.
It really depends on the position you are applying for, if the company is looking for a FE Developer who is really good at CSS and have an eye for good design, having a good looking portfolio should be encouraged but optional, as an Interviewer myself I like to see a portfolios with links to source code in case is needed or possible, just to review the coding practices, also I know by my own experience that a lot of times developers work on private Github repos and they are not able to share what they have coded before, also all the code in their repos could be purely copy and paste and not actually their work, I will never reject any candidate because of not having one or the other, I will reject them for failing interviews, where I assess what matters to the specific role, if I fail at evaluating something, it will be completely my fault.
wow!
I am applying for jobs lately. every job require a portfolio website to apply.
Appreciate your comment by the way. it's really insightful.
Bizarre - I have never once seen or written a job description for a developer that requires a portfolio - that is in over 25 years of professional experience
do you want to learn Html, CSS?
A small suggestion from me, In the contact section your email and phone should be clickable which can be done by giving them links like 'mailto:coderamrin@gmail.com' and 'tel:+8801624890723' respectively.
Btw thanks for this detailed article.
JazakAllah brother.
will add that soon. : )
Tailwind CSS is such an Amazing thing !!
yeah, it is.
After i've learned tailwind, now I build all my project with it.
I am building a project in office. Also building portfolio site for client. You code repository surrely helpful for me.
I am glad it was helpful Alwaisy :)
Nice, thanks for sharing 🔥
glad you liked it John.
👍
Some comments may only be visible to logged-in visitors. Sign in to view all comments.