├── .eslintrc.json ├── .gitignore ├── LICENSE.md ├── README.md ├── app ├── Footer.tsx ├── Header.tsx ├── HomePage.tsx ├── globals.css ├── head.tsx ├── layout.tsx └── page.tsx ├── components ├── About.tsx ├── CallToAction.tsx ├── Contact.tsx ├── Hero.tsx ├── SectionWrapper.tsx ├── Socials.tsx ├── experiences │ ├── ExperienceCard.tsx │ └── Experiences.tsx ├── projects │ ├── ProjectCard.tsx │ └── Projects.tsx └── skills │ ├── SkillCard.tsx │ └── Skills.tsx ├── data.json ├── firebase.ts ├── next.config.js ├── package-lock.json ├── package.json ├── pages └── api │ └── mail.ts ├── postcss.config.js ├── public ├── contact.png ├── favicon.ico ├── herobg.jpg ├── herobgc.jpg ├── nextjs.svg ├── portfolio-fork-dark.png ├── portfolio-fork.png ├── vercel.svg ├── waving-hand.gif └── waving-hand.png ├── tailwind.config.js ├── tsconfig.json └── types └── main.ts /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | .pnpm-debug.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | 38 | /.vscode/ -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Jigar Sable 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Portfolio](https://res.cloudinary.com/lifecodes/image/upload/v1678684352/Portfolio/l7b1gz61rh3hgoz5qzta.png) 2 | 3 |
4 | · 5 | Next Portfolio built in Next.js + TypeScript + Tailwind CSS + Firebase 6 | · 7 |
8 |
9 | 10 |

11 | 12 | 13 | 14 | 15 |

16 | 17 |

18 | Introduction • 19 | Tech Stack • 20 | Development • 21 | Deployment • 22 | License 23 |

24 | 25 |
26 | 27 | ## Introduction 👋 28 | 29 | Next Portfolio is built using Next.js and Tailwind CSS for a modern design and rapid development. TypeScript is utilized for code clarity and safety. Additionally, Firebase is being integrated for backend services such as realtime-database. The result is a dynamic and functional portfolio website that showcases the developer's skills and experience. 30 | 31 | ## Tech Stack 🛠️ 32 | 33 | - [Next.js](https://nextjs.org) 34 | - [TypeScript](https://www.typescriptlang.org) 35 | - [Tailwind CSS](https://tailwindcss.com) 36 | - [Firebase](https://firebase.google.com) 37 | - [SendGrid](https://sendgrid.com) 38 | - [Framer Motion](https://www.framer.com/motion) 39 | 40 | 59 | 60 | ## Development 💻 61 | 62 | Here are the steps to run the portfolio locally. 63 | 64 | 1. Fork [this](https://github.com/jigar-sable/next-portfolio) repository. 65 | 66 | 2. Clone your forked copy of the repo 67 | 68 | ```bash 69 | git clone https://github.com//next-portfolio.git 70 | ``` 71 | 72 | 3. Install dependencies 73 | 74 | ```bash 75 | npm i 76 | ``` 77 | 78 | 4. Create a Firebase project and select the web app 79 | 80 | 5. Create an `.env.local` file in the root directory, and add the following variables with your firebase config: 81 | ``` 82 | SENDGRID_API_KEY=XXXXXXXX 83 | NEXT_PUBLIC_FIREBASE_DATABASE_URL=XXXXXXXXXX 84 | MAIL_FROM=YOUR_MAIL_ID 85 | MAIL_TO=YOUR_MAIL_ID 86 | ``` 87 | 88 | 89 | > **Note**: `SENDGRID_API_KEY` - Create an API key from "Settings" -> "API Keys" with "Restricted Access" to only "Mail Send" 90 | 91 | 1. Update the sample [data.json](https://github.com/jigar-sable/next-portfolio/blob/main/data.json) provided, with your data or directly import the same and edit using firebase later. (For storing images you can use [Cloudinary](https://cloudinary.com) or [Firebase Storage](https://firebase.google.com/docs/storage)) 92 | 93 | 2. Import json data 94 | 95 | - Go to [Firebase Console](https://console.firebase.google.com) and select your project 96 | - Go to "Database" -> "Realtime Database" -> "Import JSON" and import the [data.json](https://github.com/jigar-sable/next-portfolio/blob/main/data.json) file 97 | 98 | 3. Run the project 99 | 100 | ```bash 101 | npm run dev 102 | ``` 103 | 104 | ## Deployment 🚀 105 | 106 | 1. Create a Vercel account and select "Import Project" 107 | 108 | 2. Select the forked repository and deploy 109 | 110 | 3. Add the following environment variables in the Vercel dashboard: 111 | ``` 112 | SENDGRID_API_KEY=XXXXXXXX 113 | NEXT_PUBLIC_FIREBASE_DATABASE_URL=XXXXXXXXXX 114 | MAIL_FROM=YOUR_MAIL_ID 115 | MAIL_TO=YOUR_MAIL_ID 116 | ``` 117 | 4. Hurray! You successfully deployed the portfolio🥳 118 | 119 | ## License 📄 120 | 121 | This project is licensed under the MIT License - see the [LICENSE.md](https://github.com/jigar-sable/next-portfolio/blob/main/LICENSE.md) 122 | 123 | 136 | -------------------------------------------------------------------------------- /app/Footer.tsx: -------------------------------------------------------------------------------- 1 | import { social } from "@/types/main"; 2 | import { useTheme } from "next-themes"; 3 | import Image from "next/image"; 4 | import Link from "next/link"; 5 | import React from "react"; 6 | import * as Fa from 'react-icons/fa'; 7 | 8 | export default function Footer({ socials, name }: { socials: social[], name: string }) { 9 | 10 | const { theme } = useTheme() 11 | 12 | return ( 13 | 47 | ) 48 | } -------------------------------------------------------------------------------- /app/Header.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | import { useState, useEffect } from 'react' 3 | import { useTheme } from 'next-themes' 4 | import Link from 'next/link' 5 | import { Link as ScrollLink } from 'react-scroll' 6 | import { FiSun, FiMoon } from 'react-icons/fi' 7 | import { FaNodeJs } from 'react-icons/fa' 8 | import { CgClose, CgMenuRight } from 'react-icons/cg' 9 | 10 | export default function Header({ logo }: { logo: string }) { 11 | 12 | const [navCollapse, setNavCollapse] = useState(true) 13 | const [scroll, setScroll] = useState(false) 14 | const { theme, setTheme } = useTheme() 15 | 16 | useEffect(() => { 17 | const updateScroll = () => { 18 | window.scrollY >= 90 ? setScroll(true) : setScroll(false) 19 | } 20 | window.addEventListener('scroll', updateScroll) 21 | }, []) 22 | 23 | 24 | const navs = ['home', 'about', 'projects', 'experience', 'contact'] 25 | 26 | return ( 27 |
28 | 56 | 57 | 68 | 69 |
70 |
setNavCollapse(true)}>
71 | 72 |
73 | setNavCollapse(true)} /> 74 | 75 | {navs.slice(0, 4).map((e) => ( 76 | setNavCollapse(true)} 85 | > 86 | {e} 87 | 88 | ))} 89 | setNavCollapse(true)} 95 | className='px-6 py-1.5 rounded-md bg-violet-600 hover:bg-violet-700 text-white text-center'> 96 | Contact 97 | 98 |
99 |
100 | 101 |
102 | ) 103 | } -------------------------------------------------------------------------------- /app/HomePage.tsx: -------------------------------------------------------------------------------- 1 | 'use client'; 2 | import { data } from "@/types/main"; 3 | import Hero from "@/components/Hero"; 4 | import About from "@/components/About"; 5 | import Skills from "@/components/skills/Skills"; 6 | import Projects from "@/components/projects/Projects"; 7 | import Socials from "@/components/Socials"; 8 | import Experiences from "@/components/experiences/Experiences"; 9 | import Contact from "@/components/Contact"; 10 | import CallToAction from "@/components/CallToAction"; 11 | import Header from "./Header"; 12 | import Footer from "./Footer"; 13 | 14 | interface Props { 15 | data: data, 16 | } 17 | 18 | const HomePage = ({ data }: Props) => { 19 | return ( 20 | <> 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |