DEV Community

Cover image for Neubrutalism React TypeScript Tailwind Portfolio Website
Codex
Codex

Posted on โ€ข Edited on

1

Neubrutalism React TypeScript Tailwind Portfolio Website

๐Ÿ—๏ธ Neubrutalism React TypeScript Tailwind Portfolio Website ๐Ÿ—๏ธ

Explore the bold and vibrant world of neubrutalism design with this responsive portfolio website! Built with cutting-edge tools like Vite, React, TypeScript, and Tailwind CSS, this project is a perfect showcase of modern web design principles and creativity.

A screenshot of a developer's code editor displaying a React component with routing and layout structure

๐Ÿ’ป Whatโ€™s Inside?

  • Bold and Modern Home Page
  • Showcase Portfolio Page
  • Informative About Page
  • Functional Contact Form

โœจ Why? If youโ€™re into neubrutalism aesthetics or looking for inspiration for your next portfolio, this project is the perfect example of how to transform a Figma prototype into a fully functional website. Whether you're a developer or designer, this video has something for you!

๐Ÿ‘€ Like, Share & Subscribe for more inspiring projects like this. Drop a comment and let us know what you think about the neubrutalism design trend! ๐ŸŒŸ

Features of the Portfolio

1. Home Page

The Home page of the website showcases a modern and minimalistic approach, using bold colors and typography, staying true to the neubrutalism style. It includes an engaging Hero section, a showcase of tools used in the development, services, and a testimonials section to build trust and credibility.

Home.tsx

import React from 'react';
import { Hero, Tools, ServicesSection, PortfolioGrid, Testimonials, ContactSection } from '../components';
import { HomeProps } from '../interfaces/interfaces';

const Home: React.FC<HomeProps> = ({ tools, testimonials, portfolioItems, onContactClick }) => {
  return (
    <div>
      <Hero />
      <Tools tools={tools} />
      <ServicesSection />
      <PortfolioGrid items={portfolioItems} />
      <Testimonials testimonials={testimonials} />
      <ContactSection ={onContactClick} />
    </div>
  );
};

export default Home;
Enter fullscreen mode Exit fullscreen mode

2. Portfolio Page

The Portfolio Page is built to display your projects in a grid format, following a modular layout that can easily expand to show more content. The loadMoreItems functionality is implemented to dynamically load more portfolio items.

Portfolio.tsx

import React, { useState } from 'react';
import { Button, CardComponent } from '../components';
import { PortfolioProps } from '../interfaces/interfaces';

const Portfolio: React.FC<PortfolioProps> = ({ portfolioItems }) => {
  const [visibleItems, setVisibleItems] = useState<number>(6); 

  const loadMoreItems = () => {
    setVisibleItems(prevVisibleItems => prevVisibleItems + 3);
  };

  return (
    <div className="min-h-screen text-black font-sans">
      <main className="container mx-auto px-4 py-16">
        <h1 className="text-5xl font-bold mb-12 text-center">My Projects</h1>
        <div className="grid grid-cols-1 md:grid-cols-2 gap-16 lg:px-16">
          {portfolioItems.slice(0, visibleItems).map((item, index) => (
            <CardComponent key={item.id} item={item} index={index} />
          ))}
        </div>

        {visibleItems < portfolioItems.length && (
          <div className="mt-16 text-center">
            <Button ={loadMoreItems} bgColor="bg-purple-400">See More</Button>
          </div>
        )}
      </main>
    </div>
  );
};

export default Portfolio;
Enter fullscreen mode Exit fullscreen mode

3. About Page

The About Page is where you can introduce yourself, your skills, and some fun facts. It uses a profile card that can be expanded with relevant information. The design is simple, focusing on typography and color contrasts to maintain the neubrutalism aesthetic.

About.tsx

import { useNavigate } from 'react-router-dom';
import { skills, funFacts, iconColors } from '../data/dataItems';
import { SectionWithBorderProps } from '../interfaces/interfaces';
import { Button, ProfileImage } from '../components';
import { Zap } from '../icons';

const About: React.FC = () => {
  return (
    <div className="min-h-screen text-black font-sans">
      <main className="container mx-auto px-4 py-16">
        <SectionWithBorder title="About Me">
          <div className="flex flex-col md:flex-row gap-8">
            <ProfileCard />
            <ProfileDescription />
          </div>
        </SectionWithBorder>

        <SectionWithBorder title="Fun Facts About Me">
          <ul className="list-disc list-inside space-y-2">
            {funFacts.map((fact, index) => (
              <li key={index}>{fact}</li>
            ))}
          </ul>
        </SectionWithBorder>
      </main>
    </div>
  );
};

const SectionWithBorder: React.FC<SectionWithBorderProps> = ({ title, children }) => {
  return (
    <div className="relative p-1 mb-12 border-4 border-black">
      <div className="relative z-10 bg-white p-8">
        <h1 className="text-4xl font-bold mb-6">{title}</h1>
        {children}
      </div>
    </div>
  );
};

const ProfileCard: React.FC = () => {
  return (
    <div className="md:w-1/3">
      <div className="relative w-full aspect-square mb-4">
        <ProfileImage />
      </div>
      <h2 className="text-2xl font-bold mb-2">Zainab</h2>
      <p className="text-lg mb-4">UI/UX Designer & Developer</p>
      <div className="flex space-x-4">
        {iconColors.map((icon, index) => (
          <div key={index} className={`${icon.bgColor} rounded-full border-2 border-black p-2 transition-colors`}>
            <Zap className="w-6 h-6" />
          </div>
        ))}
      </div>
    </div>
  );
};

const ProfileDescription: React.FC = () => {
  const navigate = useNavigate();

  const handleButtonClick = () => {
    navigate('/portfolio');
  };

  return (
    <div className="md:w-2/3">
      <p className="text-lg mb-6">
        Hey there! I'm Zainab, a passionate UI/UX designer and developer with a knack for creating engaging digital experiences...
      </p>
      <h3 className="text-2xl font-bold mb-4">My Skills</h3>
      <div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
        {skills.map(({ icon: Icon, text, bgColor }, index) => (
          <div key={index} className={`flex items-center space-x-2 ${bgColor} p-3 border-4 border-black`}>
            <Icon className="w-6 h-6" />
            <span>{text}</span>
          </div>
        ))}
      </div>
      <div className="flex justify-center sm:justify-center md:justify-start">
        <Button ={handleButtonClick} bgColor="bg-blue-400" textColor="text-white">
          Check Out My Work
        </Button>
      </div>
    </div>
  );
};

export default About;
Enter fullscreen mode Exit fullscreen mode

4. Contact Form Modal

The Contact Form is accessible through a button on the Home page. It opens in a modal overlay with a clean and simple layout.

App.tsx (Contact Modal)

import { useState, useEffect } from 'react';
import { Routes, Route, useLocation } from 'react-router-dom';
import { Navbar, Footer, ContactForm } from './components';
import { tools, testimonials, portfolioItems } from './data/dataItems';
import { X } from './icons';

export default function App() {
  const location = useLocation();
  const [contactFormOpen, setContactFormOpen] = useState(false);
  const [portfolioItemsState] = useState(portfolioItems);

  const handleButtonClick = () => {
    setContactFormOpen(true);
  };

  useEffect(() => {
    window.scrollTo(0, 0);
  }, [location.pathname]);

  return (
    <div className="app-container overflow-hidden">
      <Navbar setContactFormOpen={handleButtonClick} />
      <Routes>
        <Route path="/" element={<Home tools={tools} testimonials={testimonials} portfolioItems={portfolioItemsState} onContactClick={handleButtonClick} />} />
        <Route path="/portfolio" element={<Portfolio portfolioItems={portfolioItemsState} />} />
        <Route path="/about" element={<About />} />
      </Routes>
      <Footer />

      {contactFormOpen && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
          <div className="bg-white p-8 border-4 border-black shadow-[16px_16px_0px_0px_#303030] max-w-md w-full">
            <button ={() => setContactFormOpen(false)} className="float-right">
              <X className="w-6 h-6" />
            </button>
            <h2 className="text-3xl font-bold mb-4">Send us a message</h2>
            <ContactForm ={() => setContactFormOpen(false)} />
          </div>
        </div>
      )}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

With the Neubrutalism aesthetic, this project emphasizes strong contrast, bold typography, and clear separation between sections. Itโ€™s a modern design philosophy thatโ€™s perfect for portfolio websites, especially if you want to stand out with creative, minimalist elements.

If you'd like to check out the full project, download here

๐ŸŽจ Design Inspiration: Figma Prototype

Video --> https://youtu.be/kNqqrcUOdrU

#React #PortfolioWebsite #TypeScript #TailwindCSS #WebDesign #ResponsivePortfolio #FrontendDevelopment #ReactProject

Sentry blog image

How I fixed 20 seconds of lag for every user in just 20 minutes.

Our AI agent was running 10-20 seconds slower than it should, impacting both our own developers and our early adopters. See how I used Sentry Profiling to fix it in record time.

Read more

Top comments (0)

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

๐Ÿ‘‹ Kindness is contagious

Immerse yourself in a wealth of knowledge with this piece, supported by the inclusive DEV Communityโ€”every developer, no matter where they are in their journey, is invited to contribute to our collective wisdom.

A simple โ€œthank youโ€ goes a long wayโ€”express your gratitude below in the comments!

Gathering insights enriches our journey on DEV and fortifies our community ties. Did you find this article valuable? Taking a moment to thank the author can have a significant impact.

Okay