├── .eslintrc.json
├── .DS_Store
├── public
├── .DS_Store
├── images
│ ├── .DS_Store
│ ├── 1ds.jpg
│ ├── favicon.png
│ ├── profile.png
│ ├── guess-game.png
│ ├── snake-game.png
│ ├── landing-page.png
│ ├── movie-magnet.png
│ ├── old-favicon.png
│ ├── weather-app.png
│ ├── delta-assistant.png
│ ├── react-notes-app.png
│ ├── dice-multiplayer.png
│ ├── portfolio-website.png
│ ├── text-utility-app.png
│ ├── ar-profile-transformed.png
│ └── fmr.svg
└── files
│ └── vaheed_cv.pdf
├── .vscode
└── settings.json
├── .gitignore
├── next.config.js
├── .env.sample
├── src
├── middleware.js
├── app
│ ├── sitemap.xml.js
│ ├── experience
│ │ ├── page.jsx
│ │ └── WorkCard.jsx
│ ├── about
│ │ ├── InterestsCard.jsx
│ │ └── page.jsx
│ ├── contact
│ │ ├── MapBox.jsx
│ │ ├── page.jsx
│ │ └── ContactForm.jsx
│ ├── blogs
│ │ ├── ArticlesCard.jsx
│ │ ├── NewsLetterComponent.jsx
│ │ └── page.jsx
│ ├── projects
│ │ ├── ProjectCard.jsx
│ │ └── page.jsx
│ ├── layout.jsx
│ ├── page.jsx
│ └── skills
│ │ └── page.jsx
├── components
│ ├── RadioCards.jsx
│ ├── DrawerComponent.jsx
│ ├── ClientRootLayout.jsx
│ ├── SocialIcons.jsx
│ ├── MobileHeader.jsx
│ ├── Providers.jsx
│ └── Header.jsx
├── utils
│ ├── utils.js
│ └── constants.js
├── particlesjs.json
└── styles
│ └── main.scss
├── package.json
└── README.md
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "next/core-web-vitals"
3 | }
4 |
--------------------------------------------------------------------------------
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worker/portfolio/main/.DS_Store
--------------------------------------------------------------------------------
/public/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worker/portfolio/main/public/.DS_Store
--------------------------------------------------------------------------------
/public/images/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worker/portfolio/main/public/images/.DS_Store
--------------------------------------------------------------------------------
/public/images/1ds.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worker/portfolio/main/public/images/1ds.jpg
--------------------------------------------------------------------------------
/public/images/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worker/portfolio/main/public/images/favicon.png
--------------------------------------------------------------------------------
/public/images/profile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worker/portfolio/main/public/images/profile.png
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "cSpell.words": [
3 | "Chakra",
4 | "MAPBOX"
5 | ]
6 | }
--------------------------------------------------------------------------------
/public/files/vaheed_cv.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worker/portfolio/main/public/files/vaheed_cv.pdf
--------------------------------------------------------------------------------
/public/images/guess-game.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worker/portfolio/main/public/images/guess-game.png
--------------------------------------------------------------------------------
/public/images/snake-game.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worker/portfolio/main/public/images/snake-game.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | .next
3 | .vscode
4 | .env
5 | .env.production
6 | .env.staging
7 | .env.development
--------------------------------------------------------------------------------
/public/images/landing-page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worker/portfolio/main/public/images/landing-page.png
--------------------------------------------------------------------------------
/public/images/movie-magnet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worker/portfolio/main/public/images/movie-magnet.png
--------------------------------------------------------------------------------
/public/images/old-favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worker/portfolio/main/public/images/old-favicon.png
--------------------------------------------------------------------------------
/public/images/weather-app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worker/portfolio/main/public/images/weather-app.png
--------------------------------------------------------------------------------
/public/images/delta-assistant.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worker/portfolio/main/public/images/delta-assistant.png
--------------------------------------------------------------------------------
/public/images/react-notes-app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worker/portfolio/main/public/images/react-notes-app.png
--------------------------------------------------------------------------------
/public/images/dice-multiplayer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worker/portfolio/main/public/images/dice-multiplayer.png
--------------------------------------------------------------------------------
/public/images/portfolio-website.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worker/portfolio/main/public/images/portfolio-website.png
--------------------------------------------------------------------------------
/public/images/text-utility-app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worker/portfolio/main/public/images/text-utility-app.png
--------------------------------------------------------------------------------
/public/images/ar-profile-transformed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/worker/portfolio/main/public/images/ar-profile-transformed.png
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 |
3 | module.exports = {
4 | sassOptions: {
5 | includePaths: [path.join(__dirname, "src", "styles")],
6 | },
7 | };
8 |
--------------------------------------------------------------------------------
/.env.sample:
--------------------------------------------------------------------------------
1 | NEXT_PUBLIC_GOOGLE_ANALYTICS=
2 | NEXT_PUBLIC_MAPBOX_TOKEN=
3 | NEXT_PUBLIC_HASHNODE_API=https://api.hashnode.com/
4 | NEXT_PUBLIC_HASHNODE_API_TOKEN=
5 | NEXT_PUBLIC_HASHNODE_PUBLICATION_ID=
6 | NEXT_PUBLIC_FAB_FORM_KEY=
--------------------------------------------------------------------------------
/src/middleware.js:
--------------------------------------------------------------------------------
1 | import { NextResponse } from 'next/server'
2 |
3 | export function middleware(request) {
4 | if (request.nextUrl.pathname.startsWith('/newsletter')) {
5 | return NextResponse.rewrite("https://codersk36.hashnode.dev/api/newsletter/subscribe")
6 | }
7 | }
--------------------------------------------------------------------------------
/src/app/sitemap.xml.js:
--------------------------------------------------------------------------------
1 | export async function GET() {
2 | const baseUrl = 'https://vaheedshaik.com';
3 | const staticPages = [
4 | '', // home
5 | 'about',
6 | 'projects',
7 | 'blogs',
8 | 'contact',
9 | 'skills',
10 | 'certifications',
11 | 'experience',
12 | ];
13 |
14 | const urls = staticPages.map(
15 | (page) => ` \n ${baseUrl}/${page} \n monthly \n 0.8 \n `
16 | ).join('\n');
17 |
18 | const sitemap = `\n\n${urls}\n `;
19 |
20 | return new Response(sitemap, {
21 | headers: {
22 | 'Content-Type': 'application/xml',
23 | },
24 | });
25 | }
--------------------------------------------------------------------------------
/src/components/RadioCards.jsx:
--------------------------------------------------------------------------------
1 | import { Box, useRadio } from "@chakra-ui/react";
2 |
3 | const RadioCard = (props) => {
4 | const { getInputProps, getRadioProps } = useRadio(props);
5 |
6 | const input = getInputProps();
7 | const checkbox = getRadioProps();
8 |
9 | return (
10 |
11 |
12 |
29 | {props.children}
30 |
31 |
32 | );
33 | };
34 |
35 | export default RadioCard;
36 |
--------------------------------------------------------------------------------
/src/app/experience/page.jsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import React from "react";
3 | import WorkCard from "./WorkCard";
4 | import { Heading, SimpleGrid, Center, Box } from "@chakra-ui/react";
5 | import { workData } from "../../utils/constants";
6 | import { RevealWrapper } from "next-reveal";
7 |
8 | const Work = () => {
9 | return (
10 | <>
11 |
12 |
13 |
14 | EXPERIENCE
15 |
16 |
17 |
18 | {workData.map((data, index) => {
19 | return ;
20 | })}
21 |
22 |
23 |
24 |
25 | >
26 | );
27 | };
28 |
29 | export default Work;
30 |
--------------------------------------------------------------------------------
/src/components/DrawerComponent.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import {
3 | Drawer,
4 | DrawerBody,
5 | DrawerFooter,
6 | DrawerHeader,
7 | DrawerOverlay,
8 | DrawerContent,
9 | DrawerCloseButton,
10 | Flex,
11 | Text,
12 | } from "@chakra-ui/react";
13 |
14 | export default function DrawerComponent({
15 | p = 15,
16 | placement = "right",
17 | width,
18 | isOpen,
19 | children,
20 | onClose,
21 | btnRef,
22 | title = "",
23 | footer,
24 | }) {
25 | return (
26 |
27 |
33 |
34 |
36 |
37 |
38 | {title}
39 |
40 | {children}
41 | {footer}
42 |
43 |
44 |
45 | );
46 | }
47 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "portfolio-website-nextjs",
3 | "version": "1.0.0",
4 | "description": "This is my personal portfolio website.",
5 | "main": "index.js",
6 | "scripts": {
7 | "dev": "next dev",
8 | "build": "next build",
9 | "start": "next start",
10 | "lint": "next lint"
11 | },
12 | "keywords": [],
13 | "author": "Masood Akhtar Vaheed",
14 | "license": "ISC",
15 | "dependencies": {
16 | "@chakra-ui/icons": "^2.1.0",
17 | "@chakra-ui/next-js": "^2.1.5",
18 | "@chakra-ui/portal": "^2.1.0",
19 | "@chakra-ui/react": "^2.8.0",
20 | "@emotion/react": "^11.11.1",
21 | "@emotion/styled": "^11.11.0",
22 | "eslint": "8.47.0",
23 | "eslint-config-next": "13.4.19",
24 | "framer-motion": "^10.15.2",
25 | "mapbox-gl": "^2.15.0",
26 | "next": "13.4.19",
27 | "next-reveal": "^1.0.6",
28 | "react": "18.2.0",
29 | "react-dom": "18.2.0",
30 | "react-hook-form": "^7.45.4",
31 | "react-icons": "^5.2.1",
32 | "react-loader-spinner": "^5.4.5",
33 | "react-tsparticles": "^2.12.2",
34 | "tsparticles": "^2.12.0",
35 | "typed.js": "^2.0.16"
36 | },
37 | "devDependencies": {
38 | "sass": "^1.64.2"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/components/ClientRootLayout.jsx:
--------------------------------------------------------------------------------
1 | "use client"
2 | import React from "react";
3 | import Script from "next/script";
4 | import { Providers } from "./Providers";
5 | import Header from "./Header";
6 | import "../styles/main.scss";
7 |
8 | const ClientRootLayout = ({ children }) => {
9 | return (
10 |
11 |
16 |
20 |
21 |
31 |
32 |
33 | {children}
34 |
35 |
36 |
37 | );
38 | };
39 |
40 | export default ClientRootLayout;
--------------------------------------------------------------------------------
/src/components/SocialIcons.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { socialMediaLinks } from "../utils/constants";
3 | import { Flex } from "@chakra-ui/react";
4 | import { Icon } from "@chakra-ui/react";
5 | import { Link } from "@chakra-ui/next-js";
6 |
7 | const SocialIcons = () => {
8 | return (
9 |
15 | {socialMediaLinks.map((linkData, index) => (
16 |
35 |
36 |
37 | ))}
38 |
39 | );
40 | };
41 |
42 | export default SocialIcons;
43 |
--------------------------------------------------------------------------------
/src/components/MobileHeader.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 | import { useDisclosure, Flex, Button, VStack } from "@chakra-ui/react";
3 | import DrawerComponent from "./DrawerComponent";
4 | import { IoMdMenu } from "react-icons/io";
5 | import { Link } from "@chakra-ui/next-js";
6 | import React from "react";
7 | import { links } from "../utils/constants";
8 |
9 | export default function MobileHeader({ pathname }) {
10 | const { isOpen, onOpen, onClose } = useDisclosure();
11 | const btnRef = React.useRef();
12 |
13 | useEffect(() => {
14 | onClose();
15 | }, [pathname]);
16 |
17 | return (
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | {links.map((link, index) => (
26 |
36 | {link.text}
37 |
38 | ))}
39 |
40 |
41 |
42 | );
43 | }
44 |
--------------------------------------------------------------------------------
/src/components/Providers.jsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import { CacheProvider } from '@chakra-ui/next-js'
4 | import { ChakraProvider, extendTheme } from '@chakra-ui/react'
5 |
6 | export function Providers({
7 | children
8 | }) {
9 |
10 | const customTheme = extendTheme({
11 | config: {
12 | initialColorMode: "dark",
13 | useSystemColorMode: false,
14 | },
15 | colors: {
16 | blueTheme: {
17 | // current active theme
18 | bg: "#02001E",
19 | navBg: "rgba(10, 25, 47, 0.85)",
20 | navLinkActive:"#64ffda",
21 | navShadow:"rgba(2,12,27,0.7)",
22 | card:"#112240",
23 | cardHover:"#176B87"
24 | },
25 | defaultTheme:{
26 | bg: "#02001E",
27 | navBg: "#200b8b3c",
28 | navLinkActive:"#16FF00",
29 | card:"#213363",
30 | cardHover:"#213d8d"
31 | },
32 | hover:{
33 | gray:"rgba(0, 0, 0, 0.6)"
34 | },
35 | social:{
36 | instagram:"#D53F8C",
37 | instagramHover:"#FF63B4",
38 | linkedin:"#0072b1",
39 | linkedinHover:"#1282B1",
40 | twitter:"#00acee",
41 | twitterHover:"#63C5F4",
42 | hashnode:"#265FF7",
43 | hashnodeHover:"#7A84E6"
44 | }
45 | },
46 | });
47 | return (
48 |
49 |
50 | {children}
51 |
52 |
53 | )
54 | }
--------------------------------------------------------------------------------
/src/app/about/InterestsCard.jsx:
--------------------------------------------------------------------------------
1 | "use client"
2 | import React from "react";
3 | import { Card, Heading, Icon, Box, useColorModeValue } from "@chakra-ui/react";
4 |
5 | const InterestsCard = ({ interest, icon }) => {
6 | const cardBg = useColorModeValue("white", "gray.800");
7 | const borderColor = useColorModeValue("gray.200", "gray.700");
8 | const iconColor = useColorModeValue("blue.500", "blue.300");
9 |
10 | return (
11 |
32 |
42 |
43 |
44 |
49 | {interest}
50 |
51 |
52 | );
53 | };
54 |
55 | export default InterestsCard;
--------------------------------------------------------------------------------
/src/app/contact/MapBox.jsx:
--------------------------------------------------------------------------------
1 | import React, { useRef, useEffect } from "react";
2 | import {
3 | Modal,
4 | ModalOverlay,
5 | ModalContent,
6 | ModalCloseButton,
7 | ModalBody,
8 | Box,
9 | } from "@chakra-ui/react";
10 | import mapboxgl from "mapbox-gl";
11 |
12 | const MapBox = ({ isOpen, onClose }) => {
13 | const mapContainer = useRef(null);
14 | const map = useRef(null);
15 |
16 | useEffect(() => {
17 | // Map box was trying to find container and on initial load it was not getting it from the DOM, so it was not rendering.
18 | setTimeout(() => {
19 | if (isOpen) {
20 | mapboxgl.accessToken = process.env.NEXT_PUBLIC_MAPBOX_TOKEN;
21 | map.current = new mapboxgl.Map({
22 | container: mapContainer.current,
23 | style: "mapbox://styles/mapbox/streets-v11",
24 | center: [78.474, 17.385],
25 | zoom: 10,
26 | });
27 |
28 | }
29 | });
30 |
31 | return () => {
32 | if (map.current) {
33 | map.current.remove();
34 | map.current = null;
35 | }
36 | };
37 | }, [isOpen]);
38 |
39 | return (
40 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | );
55 | };
56 |
57 | export default MapBox;
58 |
--------------------------------------------------------------------------------
/src/utils/utils.js:
--------------------------------------------------------------------------------
1 | import { query } from "./constants";
2 |
3 | export const getArticlesData = async () => {
4 | const allArticles = [];
5 | let hasNextPage = true;
6 | let endCursor="";
7 |
8 | while (hasNextPage) {
9 | const response = await fetch(process.env.NEXT_PUBLIC_HASHNODE_API, {
10 | method: "POST",
11 | headers: {
12 | "Content-Type": "application/json",
13 | },
14 | body: JSON.stringify({
15 | query,
16 | variables: { after: endCursor },
17 | }),
18 | });
19 |
20 |
21 | const data = await response.json();
22 | const articles = data.data.publication.posts.edges;
23 | allArticles.push(...articles);
24 | hasNextPage = data.data.publication.posts.pageInfo.hasNextPage;
25 | endCursor = data.data.publication.posts.pageInfo.endCursor;
26 | }
27 | return allArticles;
28 | };
29 |
30 | export const subscribeToNewsletter = async (email) => {
31 | const publicationId = process.env.NEXT_PUBLIC_HASHNODE_PUBLICATION_ID;
32 | const url = "/newsletter";
33 | const headers = new Headers();
34 | headers.append("Content-Type", "application/json");
35 |
36 | const body = JSON.stringify({
37 | email,
38 | publicationId,
39 | });
40 |
41 | const requestOptions = {
42 | method: "POST",
43 | headers,
44 | body,
45 | redirect: "follow",
46 | };
47 |
48 | try {
49 | const response = await fetch(url, requestOptions);
50 | const result = await response.json();
51 | return result;
52 | } catch (error) {
53 | console.log("error", error);
54 | throw error;
55 | }
56 | };
57 |
--------------------------------------------------------------------------------
/src/components/Header.jsx:
--------------------------------------------------------------------------------
1 | import { Flex, HStack, chakra } from "@chakra-ui/react";
2 | import { Link } from "@chakra-ui/next-js";
3 | import React from "react";
4 | import MobileHeader from "./MobileHeader";
5 | import { links } from "../utils/constants";
6 | import { usePathname } from "next/navigation";
7 |
8 | export default function Header() {
9 | const pathname = usePathname();
10 |
11 | return (
12 |
50 | );
51 | }
52 |
--------------------------------------------------------------------------------
/src/app/blogs/ArticlesCard.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import {
3 | Card,
4 | CardBody,
5 | Text,
6 | Button,
7 | Image,
8 | Heading,
9 | Icon,
10 | Box,
11 | } from "@chakra-ui/react";
12 | import { FaExternalLinkAlt } from "react-icons/fa";
13 |
14 | const ArticlesCard = (props) => {
15 | const { data, setActiveCard, onOpen } = props;
16 | const { title, coverImage, slug, brief } = data;
17 | const articleUrl = `https://codersk36.hashnode.dev/${slug}`;
18 | return (
19 | <>
20 |
27 |
28 |
34 |
35 | {title}
36 |
37 |
38 | {brief.substring(0, 100)}...
39 | {
47 | setActiveCard(data)
48 | onOpen(true);
49 | }}
50 | >
51 | Read more
52 |
53 |
54 |
61 | Read here
62 |
63 |
64 |
65 |
66 | >
67 | );
68 | };
69 |
70 | export default ArticlesCard;
71 |
--------------------------------------------------------------------------------
/src/app/projects/ProjectCard.jsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import React, { useState } from "react";
3 | import { Card, ScaleFade, Image, Text, Link, Icon,Flex } from "@chakra-ui/react";
4 | import { FaLink,FaGithub } from "react-icons/fa6";
5 |
6 | const ProjectCard = (props) => {
7 | const { title, image, link, source } = props.data;
8 | const [showHover, setShowHover] = useState(false);
9 | const linkHover = {fill:"blueTheme.navLinkActive",transition:"all ease-in-out 0.5s"}
10 |
11 | return (
12 |
13 |
21 | {title}
22 |
23 | setShowHover(true)}
25 | onMouseLeave={() => setShowHover(false)}
26 | zIndex={0}
27 | boxShadow="0 10px 30px -10px black"
28 |
29 | >
30 |
36 |
49 | {
50 | link !==null ?
51 |
52 | :
53 | null
54 | }
55 |
56 |
57 |
58 |
59 | );
60 | };
61 |
62 | export default ProjectCard;
63 |
--------------------------------------------------------------------------------
/src/app/projects/page.jsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import React, { useState } from "react";
3 | import ProjectCard from "./ProjectCard";
4 | import {
5 | Heading,
6 | SimpleGrid,
7 | HStack,
8 | useRadioGroup,
9 | Center,
10 | Box,
11 | Flex,
12 | } from "@chakra-ui/react";
13 | import RadioCard from "../../components/RadioCards";
14 | import { projectsData } from "../../utils/constants";
15 | import { RevealWrapper } from "next-reveal";
16 |
17 | const Projects = () => {
18 | const [selectedData, setSelectedData] = useState(projectsData);
19 | const valSelectFn = (value) =>
20 | setSelectedData(() => {
21 | return value === "ALL"
22 | ? projectsData
23 | : projectsData.filter((data) => data.type === value);
24 | });
25 | const options = ["ALL", "WEB-APP", "PROJECT"];
26 | const { getRootProps, getRadioProps } = useRadioGroup({
27 | name: "project",
28 | defaultValue: "ALL",
29 | onChange: valSelectFn,
30 | });
31 | const group = getRootProps();
32 |
33 | return (
34 |
35 |
36 |
37 | PROJECTS
38 |
39 |
40 |
41 |
42 | {options.map((value) => {
43 | const radio = getRadioProps({ value });
44 | return (
45 |
46 | {value}
47 |
48 | );
49 | })}
50 |
51 |
52 |
53 |
57 | {selectedData.map((data, index) => {
58 | return ;
59 | })}
60 |
61 |
62 |
63 |
64 | );
65 | };
66 |
67 | export default Projects;
68 |
--------------------------------------------------------------------------------
/src/app/contact/page.jsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import React,{useEffect} from "react";
3 | import ContactForm from "./ContactForm";
4 | import { Heading, Icon, Stack, Text, Tooltip,useDisclosure,Center,SimpleGrid } from "@chakra-ui/react";
5 | import { IoIosMail } from "react-icons/io";
6 | import { ImLocation } from "react-icons/im";
7 | import { Link } from "@chakra-ui/next-js";
8 | import SocialIcons from "../../components/SocialIcons";
9 | import MapBox from "./MapBox";
10 | import { RevealWrapper } from 'next-reveal'
11 |
12 |
13 | const Contact = () => {
14 | const { isOpen, onOpen, onClose } = useDisclosure();
15 |
16 | return (
17 |
18 |
19 |
20 |
21 | Let's discuss on something{" "}
22 |
23 | cool
24 | {" "}
25 | together
26 |
27 |
28 |
29 |
30 |
37 |
38 | vaheedsk36@gmail.com
39 |
40 |
41 |
42 |
43 |
44 |
45 | Hyderabad, India
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | );
57 | };
58 |
59 | export default Contact;
60 |
--------------------------------------------------------------------------------
/public/images/fmr.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/particlesjs.json:
--------------------------------------------------------------------------------
1 | {
2 | "particles": {
3 | "number": {
4 | "value": 80,
5 | "density": {
6 | "enable": true,
7 | "value_area": 800
8 | }
9 | },
10 | "color": {
11 | "value": "#ffffff"
12 | },
13 | "shape": {
14 | "type": "circle",
15 | "stroke": {
16 | "width": 0,
17 | "color": "#000000"
18 | },
19 | "polygon": {
20 | "nb_sides": 5
21 | },
22 | "image": {
23 | "src": "img/github.svg",
24 | "width": 100,
25 | "height": 100
26 | }
27 | },
28 | "opacity": {
29 | "value": 0.5,
30 | "random": false,
31 | "anim": {
32 | "enable": false,
33 | "speed": 1,
34 | "opacity_min": 0.1,
35 | "sync": false
36 | }
37 | },
38 | "size": {
39 | "value": 3,
40 | "random": true,
41 | "anim": {
42 | "enable": true,
43 | "speed": 4.795204795204795,
44 | "size_min": 0.1,
45 | "sync": true
46 | }
47 | },
48 | "line_linked": {
49 | "enable": true,
50 | "distance": 150,
51 | "color": "#ffffff",
52 | "opacity": 0.4,
53 | "width": 1
54 | },
55 | "move": {
56 | "enable": true,
57 | "speed": 6,
58 | "direction": "none",
59 | "random": false,
60 | "straight": false,
61 | "out_mode": "out",
62 | "bounce": false,
63 | "attract": {
64 | "enable": false,
65 | "rotateX": 600,
66 | "rotateY": 1200
67 | }
68 | }
69 | },
70 | "interactivity": {
71 | "detect_on": "canvas",
72 | "events": {
73 | "onhover": {
74 | "enable": false,
75 | "mode": "repulse"
76 | },
77 | "onclick": {
78 | "enable": true,
79 | "mode": "repulse"
80 | },
81 | "resize": true
82 | },
83 | "modes": {
84 | "grab": {
85 | "distance": 400,
86 | "line_linked": {
87 | "opacity": 1
88 | }
89 | },
90 | "bubble": {
91 | "distance": 400,
92 | "size": 40,
93 | "duration": 2,
94 | "opacity": 8,
95 | "speed": 3
96 | },
97 | "repulse": {
98 | "distance": 200,
99 | "duration": 0.4
100 | },
101 | "push": {
102 | "particles_nb": 4
103 | },
104 | "remove": {
105 | "particles_nb": 2
106 | }
107 | }
108 | },
109 | "retina_detect": true
110 | }
111 |
--------------------------------------------------------------------------------
/src/app/layout.jsx:
--------------------------------------------------------------------------------
1 | import Favicon from "/public/images/favicon.png";
2 | import ClientRootLayout from "../components/ClientRootLayout";
3 |
4 | export const metadata = {
5 | metadataBase: new URL('https://vaheedshaik.com'),
6 | title: {
7 | default: "Vaheed Shaik | Software Engineer",
8 | template: "%s | Vaheed Shaik"
9 | },
10 | description: "Welcome to Vaheed's Software Engineering Portfolio. Explore a diverse range of projects and see how I can bring your ideas to life. Let's connect and discuss your next venture!",
11 | keywords: [
12 | "portfolio",
13 | "app",
14 | "next.js 13",
15 | "sass",
16 | "scss",
17 | "react",
18 | "chakra",
19 | "hashnode",
20 | "best portfolio",
21 | "best portfolio website",
22 | "software engineer",
23 | "web development",
24 | "frontend developer",
25 | "full stack developer",
26 | "javascript",
27 | "typescript",
28 | "react developer",
29 | "nextjs developer",
30 | "portfolio website",
31 | "developer portfolio"
32 | ],
33 | authors: [{ name: "Vaheed Shaik" }],
34 | creator: "Vaheed Shaik",
35 | publisher: "Vaheed Shaik",
36 | formatDetection: {
37 | email: false,
38 | address: false,
39 | telephone: false,
40 | },
41 | openGraph: {
42 | type: 'website',
43 | locale: 'en_US',
44 | url: 'https://vaheedshaik.com',
45 | title: 'Vaheed Shaik | Software Engineer',
46 | description: 'Welcome to Vaheed\'s Software Engineering Portfolio. Explore a diverse range of projects and see how I can bring your ideas to life. Let\'s connect and discuss your next venture!',
47 | siteName: 'Vaheed Shaik Portfolio',
48 | images: [
49 | {
50 | url: '/images/og-image.jpg',
51 | width: 1200,
52 | height: 630,
53 | alt: 'Vaheed Shaik Portfolio Preview',
54 | },
55 | ],
56 | },
57 | twitter: {
58 | card: 'summary_large_image',
59 | title: 'Vaheed Shaik | Software Engineer',
60 | description: 'Welcome to Vaheed\'s Software Engineering Portfolio. Explore a diverse range of projects and see how I can bring your ideas to life.',
61 | images: ['/images/og-image.jpg'],
62 | creator: '@vaheedshaik',
63 | },
64 | robots: {
65 | index: true,
66 | follow: true,
67 | googleBot: {
68 | index: true,
69 | follow: true,
70 | 'max-video-preview': -1,
71 | 'max-image-preview': 'large',
72 | 'max-snippet': -1,
73 | },
74 | },
75 | icons: [{
76 | rel: 'icon',
77 | url: Favicon.src,
78 | }],
79 | verification: {
80 | google: 'Dz2xp2RtP9GiXlS5Wj_tzIm0QeRcbzKILqVNJAUAd5w',
81 | yandex: '827e25c6099be3b0',
82 | yahoo: 'EAF9D5ED84139FFD4C2CE4429F37BC3B',
83 | },
84 | };
85 |
86 | export default function RootLayout({ children }) {
87 | return {children}
88 | }
89 |
--------------------------------------------------------------------------------
/src/app/page.jsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import { useEffect, useRef, useCallback } from "react";
3 | import { Heading, Flex, Center, Image } from "@chakra-ui/react";
4 | import Typed from "typed.js";
5 | import SocialIcons from "../components/SocialIcons";
6 | import Particles from "react-tsparticles";
7 | import { loadFull } from "tsparticles";
8 | import particleConfig from "../particlesjs.json";
9 | import { RevealWrapper } from "next-reveal";
10 |
11 | export default function Home() {
12 | const typedTextRef = useRef(null);
13 | const particlesInit = useCallback(async (engine) => {
14 | await loadFull(engine);
15 | }, []);
16 |
17 | useEffect(() => {
18 | const options = {
19 | strings: ["Developer", "Coder", "Tech Blogger", "Tech Enthusiast"],
20 | typeSpeed: 50,
21 | backSpeed: 35,
22 | loop: true,
23 | };
24 |
25 | const typed = new Typed(typedTextRef.current, options);
26 | return () => {
27 | typed.destroy();
28 | };
29 | }, []);
30 |
31 | return (
32 | <>
33 |
34 |
41 |
51 |
52 |
63 |
64 |
65 |
70 | Hi, my name is
71 |
72 |
73 |
74 |
79 |
83 | Masood Akhtar
84 |
85 |
86 |
91 | Vaheed
92 |
93 |
94 |
95 |
96 |
97 | I 'm
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 | >
106 | );
107 | }
108 |
--------------------------------------------------------------------------------
/src/app/blogs/NewsLetterComponent.jsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import { useState } from "react";
3 | import {
4 | Stack,
5 | FormControl,
6 | Input,
7 | Button,
8 | useColorModeValue,
9 | Heading,
10 | Text,
11 | Container,
12 | Flex,
13 | Modal,
14 | ModalOverlay,
15 | ModalContent,
16 | ModalCloseButton,
17 | ModalBody,
18 | Box,
19 | useDisclosure,
20 | ModalHeader,
21 | } from "@chakra-ui/react";
22 | import { CheckIcon } from "@chakra-ui/icons";
23 | import { subscribeToNewsletter } from "../../utils/utils";
24 |
25 | export default function NewsLetterComponent() {
26 | const [email, setEmail] = useState("");
27 | const [state, setState] = useState("initial");
28 | const [error, setError] = useState(false);
29 | const { isOpen, onOpen, onClose } = useDisclosure();
30 |
31 | return (
32 | <>
33 |
34 |
35 |
41 | Subscribe to my Newsletter
42 |
43 | {
48 | e.preventDefault();
49 | setError(false);
50 | setState("submitting");
51 | subscribeToNewsletter(email)
52 | .then((response) => {
53 | setState(response.result);
54 | onOpen(true);
55 | })
56 | .catch((error) => {
57 | setError(true);
58 | setState("initial");
59 | console.error("An error occurred:", error);
60 | });
61 | }}
62 | >
63 |
64 | setEmail(e.target.value)}
80 | />
81 |
82 |
83 |
89 | {state === "success" ? : "Submit"}
90 |
91 |
92 |
93 |
98 | {error
99 | ? "Oh no an error occured! 😢 Please try again later."
100 | : "You won't receive any spam! ✌️"}
101 |
102 |
103 |
104 |
105 |
111 |
112 |
113 |
114 | Thank You for Subscribing
115 |
116 | You have received a confirmation mail to subscribe my hashnode blog
117 | on {email} . Please confirm it, to receive updates on my articles.
118 |
119 |
120 |
121 | >
122 | );
123 | }
124 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ⭐ Personal Portfolio Website ⭐
2 |
3 | > [Deployed here](https://vaheedshaik.tech/)
4 |
5 | ⭐ Star me on GitHub and do follow ⭐
6 |
7 | [](https://github.com/vaheedsk36/portfolio-website-nextjs/commits/main)
8 | [](https://vaheedshaik.tech/)
9 | [](https://www.linkedin.com/in/sk36)
10 | [](http://badges.mit-license.org)
11 |
12 | ## Note
13 |
14 | - Latest hashnode graphql version 16.8 syntax is added in this project for getting articles details
15 |
16 | ## Conditions of usage
17 |
18 | - Follow me on [github](https://github.com/vaheedsk36)
19 | - Follow me on [linkedin](https://www.linkedin.com/in/sk36/) (if you want to)
20 | - Star this project on github
21 |
22 | ## Tech Stack and Services Used 🛠️
23 |
24 | Explore the technologies and services that power this portfolio:
25 |
26 | 
27 | 
28 | 
29 | 
30 | 
31 |
32 | ## SEO Enhancements 🚀
33 |
34 | This portfolio is optimized for search engines using several modern SEO techniques:
35 |
36 | - **Comprehensive Metadata:** Uses advanced metadata including OpenGraph, Twitter Card, and extended keywords for better sharing and discoverability.
37 | - **Dynamic Sitemap:** Automatically generates a sitemap at `/sitemap.xml` to help search engines index all main pages (home, about, projects, blogs, contact, skills, certifications, experience).
38 | - **Robots and Verification Tags:** Includes robots directives for indexing and site verification tags for Google, Yandex, and Yahoo.
39 | - **Accessibility & Discoverability:** Metadata and sitemap improve accessibility and ensure all important pages are easily found by search engines.
40 |
41 | For further SEO improvements, you can add structured data (JSON-LD) or extend the sitemap to include dynamic content like blog posts or projects.
42 |
43 | ## Search Engine Verification Tools 🔍
44 |
45 | This project is verified with major search engines using their free webmaster tools:
46 |
47 | ### Google Search Console
48 | - **Purpose:** Monitor and maintain site's presence in Google Search
49 | - **Features:**
50 | - Search performance analytics
51 | - Indexing status
52 | - Mobile usability
53 | - Security issues
54 | - URL inspection
55 | - **Verification Code:** Implemented in metadata
56 |
57 | ### Yandex Webmaster
58 | - **Purpose:** Manage site's presence in Yandex search results
59 | - **Features:**
60 | - Search analytics
61 | - Indexing status
62 | - Crawl statistics
63 | - Site diagnostics
64 | - **Verification Code:** Implemented in metadata
65 |
66 | ### Bing Webmaster Tools
67 | - **Purpose:** Manage site's presence in both Bing and Yahoo search results
68 | - **Features:**
69 | - Search performance
70 | - SEO reports
71 | - URL submission
72 | - Site diagnostics
73 | - **Verification Code:** Implemented in metadata
74 |
75 | All these tools are completely free to use and provide valuable insights for improving your site's search engine presence.
76 |
77 | ## Setup & Deployment Instructions 🚀
78 |
79 | Follow these steps to set up and deploy your own portfolio:
80 |
81 | 1. Fork the repository
82 | 2. Run `npm install`
83 | 3. Make modifications in `app` folder files
84 | 4. Store your image assets in `public > images`
85 | 5. Store you secret keys by in a `.env` file for ref see `.env.sample`
86 | 6. For deployment, follow these [instructions](https://nextjs.org/learn/basics/deploying-nextjs-app/deploy)
87 |
88 | ## Sections 📚
89 |
90 | Explore different sections of my profile:
91 |
92 | - **🏠 Home**
93 | - **🙋♂️ About**
94 | - **🛠️ Skills**
95 | - **💼 Projects**
96 | - **🔍 Experience**
97 | - **📝 Blogs**
98 | - **📬 Contact**
99 |
100 | ## Contributing 💡
101 |
102 | To contribute, follow these steps:
103 |
104 | ### Step 1
105 |
106 | Fork or clone this repo to your local machine.
107 |
108 | ### Step 2
109 |
110 | Build your code. Implement your changes, add features, or fix issues.
111 |
112 | ### Step 3
113 |
114 | When you're ready, create a new pull request to merge your changes:
115 |
116 | - 🔃 Push your changes to your forked repo.
117 | - 👀 Await review and address any feedback.
118 |
119 | Thank you for contributing to this repo! Together, we can make it even better. 😄🚀
120 |
--------------------------------------------------------------------------------
/src/app/experience/WorkCard.jsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import React from "react";
3 | import {
4 | Card,
5 | CardBody,
6 | Image,
7 | Heading,
8 | Text,
9 | Flex,
10 | Box,
11 | VStack,
12 | Divider,
13 | } from "@chakra-ui/react";
14 |
15 | const WorkCard = (props) => {
16 | const { company, companyImg, roles } = props.data;
17 | const hasMultipleRoles = roles.length > 1;
18 |
19 | return (
20 | <>
21 |
29 |
30 |
35 |
42 |
54 |
60 | {company}
61 |
62 |
63 |
64 |
70 |
71 | {roles.map((role, index) => (
72 |
73 | {hasMultipleRoles && index > 0 && (
74 |
82 | )}
83 |
84 | {hasMultipleRoles && (
85 |
97 |
98 | {index + 1}
99 |
100 |
101 | )}
102 |
103 |
104 | {role.duration}
105 |
106 |
113 | {role.designation}
114 |
115 |
121 | {role.description}
122 |
123 |
124 |
125 |
126 | ))}
127 |
128 |
129 |
130 |
131 |
132 | >
133 | );
134 | };
135 |
136 | export default WorkCard;
137 |
--------------------------------------------------------------------------------
/src/app/contact/ContactForm.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import {
3 | Input,
4 | Textarea,
5 | NumberInput,
6 | NumberInputField,
7 | FormControl,
8 | FormLabel,
9 | FormErrorMessage,
10 | Button,
11 | Card,
12 | CardBody,
13 | useRadioGroup,
14 | Flex,
15 | Heading,
16 | Icon,
17 | Stack
18 | } from "@chakra-ui/react";
19 | import { BsFillSendFill } from "react-icons/bs";
20 | import RadioCard from "../../components/RadioCards";
21 | import { useForm } from "react-hook-form";
22 | import { useToast } from "@chakra-ui/react";
23 | import { RevealWrapper } from 'next-reveal'
24 |
25 | const ContactForm = () => {
26 | const toast = useToast();
27 | const options = ["Web Development", "Hiring", "Freelance", "Other"];
28 | const [interestedIn, setInterestedIn] = useState("Web Development");
29 | const { getRootProps, getRadioProps } = useRadioGroup({
30 | name: "interested",
31 | defaultValue: interestedIn,
32 | onChange: (value) => setInterestedIn(value),
33 | });
34 | const group = getRootProps();
35 | const {
36 | handleSubmit,
37 | register,
38 | formState: { errors },
39 | reset
40 | } = useForm();
41 | const [isLoading, setIsLoading] = useState(false);
42 |
43 | const onSubmit = async (formData) => {
44 | setIsLoading(true);
45 | formData["interested-in"] = interestedIn;
46 | const formSubmitURL = `https://fabform.io/f/${process.env.NEXT_PUBLIC_FAB_FORM_KEY}`;
47 | try {
48 | const response = await fetch(formSubmitURL, {
49 | method: "POST",
50 | headers: {
51 | "Content-Type": "application/json",
52 | },
53 | body: JSON.stringify(formData),
54 | });
55 |
56 | if (!response.ok) {
57 | throw new Error("Unable to send message ");
58 | }
59 |
60 | reset({
61 | name: "",
62 | email: "",
63 | number: "",
64 | message: "",
65 | });
66 |
67 | setIsLoading(false);
68 |
69 | toast({
70 | title: "Message sent successfully",
71 | status: "success",
72 | position: "top",
73 | duration: 9000,
74 | isClosable: true,
75 | });
76 | } catch (error) {
77 | console.error("Error sending message:", error);
78 | toast({
79 | title: error.message,
80 | status: "error",
81 | position: "top",
82 | duration: 9000,
83 | isClosable: true,
84 | });
85 | }
86 | };
87 |
88 | return (
89 | <>
90 |
91 |
92 |
93 |
94 | I'm interested in...
95 |
96 |
97 | {options.map((value) => {
98 | const radio = getRadioProps({ value });
99 | return (
100 |
101 | {value}
102 |
103 | );
104 | })}
105 |
106 |
107 |
108 | Enter Name
109 |
116 | {errors.name && (
117 | Enter your name
118 | )}
119 |
120 |
121 | Enter Email
122 |
129 | {errors.email && (
130 | Enter your email
131 | )}
132 |
133 |
134 | Enter Phone No.
135 |
136 |
140 |
141 |
142 |
143 | Enter Message
144 |
150 | {errors.message && (
151 | Enter your message
152 | )}
153 |
154 |
155 |
163 |
164 | Send Message
165 |
166 |
167 |
168 |
169 |
170 |
171 | >
172 | );
173 | };
174 |
175 | export default ContactForm;
176 |
--------------------------------------------------------------------------------
/src/app/skills/page.jsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import React from "react";
3 | import {
4 | Card,
5 | CardBody,
6 | Heading,
7 | SimpleGrid,
8 | Icon,
9 | Box,
10 | Center,
11 | VStack,
12 | Text,
13 | useColorModeValue,
14 | } from "@chakra-ui/react";
15 | import { skillsData } from "../../utils/constants";
16 | import { RevealWrapper } from "next-reveal";
17 |
18 | const Skills = () => {
19 | const cardBg = useColorModeValue("white", "gray.800");
20 | const cardHoverBg = useColorModeValue("gray.50", "gray.700");
21 | const textColor = useColorModeValue("gray.700", "white");
22 |
23 | return (
24 |
25 |
26 |
27 | SKILLS
28 |
29 |
30 |
31 | {skillsData.map((category, categoryIndex) => (
32 |
33 |
58 | {category.category}
59 |
60 |
70 | {category.skills.map((skill, skillIndex) => (
71 |
100 |
109 |
121 |
131 |
132 |
141 | {skill.name}
142 |
143 |
144 |
145 | ))}
146 |
147 |
148 | ))}
149 |
150 |
151 |
152 |
153 | );
154 | };
155 |
156 | export default Skills;
157 |
--------------------------------------------------------------------------------
/src/styles/main.scss:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Black+Ops+One&family=Courgette&family=Inter:wght@400;500&family=Manrope&family=Righteous&family=Roboto&family=Sofia&display=swap');
2 | * {
3 | margin: 0;
4 | font-family: 'Inter', sans-serif;
5 | color: white;
6 | .mapboxgl-ctrl-attrib {
7 | display: none;
8 | }
9 |
10 | .mapboxgl-ctrl-compact {
11 | display: none;
12 | }
13 | }
14 |
15 | $background-color: #02001E;
16 | $nav-container-color: #200b8b3c;
17 | $nav-link-container-color: #150639d5;
18 | $blue-400: #4299E1;
19 | $blue-500: #3182CE;
20 | $sub-header-color: #dee2e6;
21 | $default-card-color: #213363;
22 | $default-card-hover-color: #213d8d;
23 | $mustard-yellow: #FFC436;
24 | $mustard-hover-yellow: #e1ae37;
25 | $instagram-pink: #D53F8C;
26 | $linkedin-blue-color: #0072b1;
27 | $twitter-blue-color: #00acee;
28 | $form-label-gray: #6A6A6A;
29 | $neon-green-color: #16FF00;
30 | $active-green-color: #64ffda;
31 |
32 |
33 | // ******** COMMON CLASSES ********
34 |
35 | html.sr .load-hidden {
36 | visibility: hidden;
37 | }
38 |
39 | .container {
40 | margin: 2rem 7rem;
41 | }
42 |
43 | .sub-heading {
44 | font-size: 1rem;
45 | color: $sub-header-color;
46 | display: flex;
47 | align-items: center;
48 | gap: 1rem;
49 | margin-bottom: 2rem;
50 |
51 | &::after {
52 | content: "";
53 | width: 100px;
54 | height: 2px;
55 | background: $sub-header-color;
56 | border-radius: 2px;
57 | transition: width 0.3s ease-in-out;
58 | }
59 |
60 | &:hover::after {
61 | width: 150px;
62 | }
63 | }
64 |
65 | .typed-cursor {
66 | color: $neon-green-color;
67 | }
68 |
69 | .active-link {
70 | color: $active-green-color;
71 | position: relative;
72 | }
73 |
74 | .active-link::after {
75 | content: '';
76 | position: absolute;
77 | bottom: -5px;
78 | left: 17px;
79 | transform: translateX(-50%);
80 | width: 2rem;
81 | height: 2.5px;
82 | background-color: $active-green-color;
83 | }
84 |
85 | .contact-input{
86 | color: #02001E;
87 | border: 1.2px solid #9E9FA5;
88 | &:hover{
89 | border-color: #bcbcbc;
90 | }
91 | }
92 |
93 | // ******** HOMEPAGE COMPONENT ********
94 |
95 | .home-container {
96 | position: fixed;
97 | top: 0;
98 | bottom: 0;
99 | left: 0;
100 | right: 0;
101 | z-index: -1;
102 | }
103 |
104 | .body-theme {
105 | background-color: $background-color;
106 | }
107 |
108 | .typed-text {
109 | color: $neon-green-color;
110 | }
111 |
112 | // ******** ABOUT SECTION ********
113 |
114 | .about-main-container{
115 | position: absolute;
116 | top: 18rem;
117 | left: 10rem;
118 | }
119 |
120 | .name-heading{
121 | font-size: 3.7rem;
122 | }
123 |
124 | .about-container {
125 | margin: 2rem 8rem;
126 | }
127 |
128 | .about-layout-container {
129 | display: grid;
130 | grid-template-columns: 30% 70%;
131 | font-size: 1.1rem;
132 | margin-bottom: 4rem;
133 |
134 | p {
135 | text-align: justify;
136 | }
137 | };
138 |
139 | // ******** BLOGS SECTION ********
140 |
141 |
142 | .blogs-container {
143 | width: 85rem;
144 | padding: 1.3rem 0;
145 | margin: auto 3rem;
146 | }
147 |
148 | ;
149 |
150 | .blogs-grid-container {
151 | display: grid;
152 | grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
153 | }
154 |
155 | .articles-card {
156 | background-color: $default-card-color;
157 | width: 20rem;
158 | height: 30rem;
159 | margin: 0.5rem;
160 | }
161 |
162 | .article-btn {
163 | background-color: $mustard-yellow;
164 |
165 | a {
166 | &:hover {
167 | text-decoration: none;
168 | }
169 |
170 | }
171 |
172 | &:hover {
173 | background-color: $mustard-hover-yellow;
174 |
175 | }
176 | }
177 |
178 | ;
179 |
180 | // ******** CONTACT SECTION ********
181 |
182 |
183 | .contact-container {
184 | margin-top: 5rem;
185 | display: grid;
186 | grid-template-columns: 40% 55%;
187 | }
188 |
189 | .contact-text-span {
190 | font-size: 1.4rem;
191 | display: flex;
192 | align-items: center;
193 | }
194 | // keep it
195 | .contact-form-card {
196 | label {
197 | color: $form-label-gray;
198 | font-weight: 900;
199 | }
200 | }
201 |
202 | .social-container {
203 | font-size: 3rem;
204 | margin-top: 7rem;
205 |
206 | svg {
207 | padding: 10px;
208 | border-radius: 1.1rem;
209 | cursor: pointer;
210 | }
211 |
212 | .instagram {
213 | background-color: $instagram-pink;
214 | }
215 |
216 | .linkedin {
217 | background-color: $linkedin-blue-color;
218 | }
219 |
220 | .twitter {
221 | background-color: $twitter-blue-color;
222 | }
223 |
224 | }
225 |
226 | ;
227 |
228 |
229 | //! ******** iphone 12pro screen ********
230 |
231 | @media screen and (max-width: 390px) {
232 |
233 | // ******** ABOUT SECTION ********
234 |
235 | .about-main-container{
236 | top: 15rem;
237 | left: 1.22rem;
238 | text-align: center;
239 | }
240 |
241 | .name-heading{
242 | font-size: 1.8rem;
243 | margin-bottom: 3rem;
244 | }
245 |
246 | .about-container {
247 | margin: 3.5rem;
248 | }
249 |
250 | .about-layout-container {
251 | display: block;
252 | };
253 |
254 | // ******** BLOGS SECTION ********
255 |
256 | .blogs-container {
257 | margin: auto 1.6rem;
258 | };
259 |
260 | .articles-card {
261 | margin: 2rem 0.5rem;
262 | }
263 |
264 | .blogs-grid-container {
265 | display: block;
266 | }
267 |
268 | // ******** CONTACT SECTION ********
269 |
270 | .container {
271 | margin: 1.2rem;
272 | }
273 |
274 | .contact-container {
275 | margin-top: 1.5rem;
276 | display: block;
277 |
278 | .chakra-heading {
279 | font-size: 2.1rem;
280 | }
281 |
282 | .chakra-stack {
283 | margin-top: 1rem;
284 | }
285 | }
286 |
287 | .contact-text-span {
288 | font-size: 1.2rem;
289 | display: flex;
290 | align-items: center;
291 | }
292 | // Keep this one
293 | .contact-form-card {
294 | padding: 0;
295 | margin-bottom: 3rem;
296 |
297 | .chakra-heading {
298 | font-size: 1.2rem;
299 | }
300 |
301 | label {
302 | font-size: 1rem;
303 | }
304 |
305 | }
306 |
307 | .social-container {
308 | margin-bottom: 2.5rem;
309 | };
310 |
311 | }
--------------------------------------------------------------------------------
/src/app/about/page.jsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import React from "react";
3 | import {
4 | Heading,
5 | SimpleGrid,
6 | Image,
7 | Center,
8 | Box,
9 | Text,
10 | VStack,
11 | useColorModeValue,
12 | Container,
13 | Flex,
14 | Badge,
15 | Icon,
16 | } from "@chakra-ui/react";
17 | import InterestsCard from "./InterestsCard";
18 | import { interestsData } from "../../utils/constants";
19 | import { RevealWrapper } from "next-reveal";
20 | import { FaGithub, FaLinkedin } from "react-icons/fa";
21 |
22 | const Page = () => {
23 | const textColor = useColorModeValue("gray.700", "white");
24 | const highlightColor = useColorModeValue("blue.500", "blue.300");
25 | const cardBg = useColorModeValue("white", "gray.800");
26 | const cardHoverBg = useColorModeValue("gray.50", "gray.700");
27 |
28 | return (
29 |
30 |
31 |
32 |
33 |
37 | ABOUT
38 |
39 |
40 |
45 |
52 |
65 |
71 |
89 |
90 | GitHub
91 |
92 |
110 |
111 | LinkedIn
112 |
113 |
114 |
115 |
116 |
129 |
135 | 👋 Hey there
136 |
137 |
142 | I'm Vaheed , a passionate
143 | software developer. I specialize in{" "}
144 | Web Development , crafting
145 | seamless user experiences and robust backend solutions. With a
146 | knack for problem-solving, I thrive on creating elegant code
147 | that makes an impact. I'm always exploring new tools and
148 | techniques to stay at the forefront of the ever-evolving tech
149 | landscape.
150 |
151 |
156 | 📫 Open to collaborations and exciting projects, I'm
157 | eager to connect with fellow developers and tech enthusiasts.
158 | Let's build something amazing together!
159 |
160 |
165 | Happy coding! 🖥️
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
178 | INTERESTS
179 |
180 |
184 | {interestsData.map((data, index) => (
185 |
190 | ))}
191 |
192 |
193 |
194 |
195 |
196 | );
197 | };
198 |
199 | export default Page;
200 |
--------------------------------------------------------------------------------
/src/app/blogs/page.jsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import React, { useEffect, useMemo, useState } from "react";
3 | import ArticlesCard from "./ArticlesCard";
4 | import {
5 | Heading,
6 | Box,
7 | Center,
8 | SimpleGrid,
9 | Modal,
10 | ModalOverlay,
11 | ModalContent,
12 | ModalCloseButton,
13 | ModalBody,
14 | useDisclosure,
15 | ModalHeader,
16 | Link,
17 | Input,
18 | Select,
19 | Flex,
20 | InputGroup,
21 | InputLeftElement,
22 | useColorModeValue,
23 | } from "@chakra-ui/react";
24 | import { Search2Icon } from "@chakra-ui/icons";
25 | import NewsLetterComponent from "./NewsLetterComponent";
26 | import { getArticlesData } from "../../utils/utils";
27 | import { FidgetSpinner } from "react-loader-spinner";
28 | import { RevealWrapper } from "next-reveal";
29 |
30 | const Blogs = () => {
31 | const { isOpen, onOpen, onClose } = useDisclosure();
32 | const [articlesData, setArticlesData] = useState([]);
33 | const [isLoading, setIsLoading] = useState(true);
34 | const [activeCard, setActiveCard] = useState();
35 | const [search, setSearch] = useState("");
36 | const [sortOrder, setSortOrder] = useState("newest");
37 |
38 | // Color mode values for controls (move hooks to top level)
39 | const controlsBg = useColorModeValue("white", "gray.800");
40 | const controlsBorder = useColorModeValue("gray.200", "gray.700");
41 | const controlsShadow = useColorModeValue("md", "dark-lg");
42 | const inputBg = useColorModeValue("gray.50", "gray.700");
43 |
44 | const activeCardBrief = useMemo(() => {
45 | // article brief from hashnode, is not completely full itgives ... at end so we have fixed the issue by omitting the string
46 | const fixedBrief = activeCard?.brief
47 | ?.substring(0, activeCard.brief.length - 3)
48 | .split(". ");
49 | fixedBrief?.pop();
50 | return `${fixedBrief?.join(". ")}.`;
51 | }, [activeCard]);
52 | const onCloseHandler = () => {
53 | setActiveCard([]);
54 | onClose();
55 | };
56 |
57 | useEffect(() => {
58 | getArticlesData().then((data) => {
59 | setArticlesData(data.map(data=>data.node));
60 | setIsLoading(false);
61 | });
62 | }, []);
63 |
64 | // Filter and sort articles
65 | const filteredAndSortedArticles = useMemo(() => {
66 | let filtered = articlesData.filter(article => {
67 | const searchLower = search.toLowerCase();
68 | return (
69 | article.title.toLowerCase().includes(searchLower) ||
70 | article.brief?.toLowerCase().includes(searchLower)
71 | );
72 | });
73 |
74 | return filtered.sort((a, b) => {
75 | const dateA = new Date(a.publishedAt);
76 | const dateB = new Date(b.publishedAt);
77 | return sortOrder === "newest" ? dateB - dateA : dateA - dateB;
78 | });
79 | }, [articlesData, search, sortOrder]);
80 |
81 | return (
82 | <>
83 |
84 | {isLoading ? (
85 |
91 |
100 |
101 | ) : (
102 |
103 |
104 | BLOGS
105 |
106 |
107 |
108 | {/* Attractive Controls Row */}
109 |
126 |
127 |
128 |
129 |
130 | setSearch(e.target.value)}
134 | borderRadius="lg"
135 | bg={inputBg}
136 | _focus={{ borderColor: "blue.400", boxShadow: "0 0 0 1px #4299e1" }}
137 | _hover={{ borderColor: "blue.300" }}
138 | fontSize="md"
139 | h="45px"
140 | />
141 |
142 | setSortOrder(e.target.value)}
145 | borderRadius="lg"
146 | bg={inputBg}
147 | _focus={{ borderColor: "blue.400", boxShadow: "0 0 0 1px #4299e1" }}
148 | _hover={{ borderColor: "blue.300" }}
149 | fontSize="md"
150 | maxW={{ base: "100%", md: "40%" }}
151 | h="45px"
152 | position="relative"
153 | zIndex={1}
154 | sx={{
155 | '& option': {
156 | whiteSpace: 'normal',
157 | wordBreak: 'break-word',
158 | padding: '8px'
159 | }
160 | }}
161 | >
162 | Newest First
163 | Oldest First
164 |
165 |
166 |
167 |
175 | {filteredAndSortedArticles?.map((data, index) => (
176 |
180 | ))}
181 |
182 |
183 |
184 | )}
185 |
191 |
192 |
193 |
194 |
198 | {activeCard?.title}
199 |
200 |
201 |
202 |
203 | {activeCardBrief}
204 |
205 |
206 |
207 |
208 | >
209 | );
210 | };
211 |
212 | export default Blogs;
213 |
--------------------------------------------------------------------------------
/src/utils/constants.js:
--------------------------------------------------------------------------------
1 | import {
2 | FaHtml5,
3 | FaCss3,
4 | FaReact,
5 | FaSass,
6 | FaPython,
7 | FaNodeJs,
8 | FaDocker,
9 | FaGithub,
10 | FaInstagram,
11 | FaLinkedin,
12 | FaMediumM,
13 | FaJava
14 | } from "react-icons/fa";
15 |
16 | import { FaXTwitter } from "react-icons/fa6";
17 |
18 | import {
19 | TbBrandTypescript,
20 | TbBrandJavascript,
21 | TbBrandCpp,
22 | TbBrandRedux,
23 | TbBrandBootstrap
24 | } from "react-icons/tb";
25 | import { BiLogoJquery } from "react-icons/bi";
26 | import {
27 | SiPug,
28 | SiExpress,
29 | SiPostman,
30 | SiGnubash,
31 | SiNextdotjs,
32 | } from "react-icons/si";
33 | import { AiFillCode } from "react-icons/ai";
34 | import { FaHashnode } from "react-icons/fa6";
35 | import {
36 | BsGlobe,
37 | BsCodeSlash,
38 | BsRobot,
39 | BsFileBarGraph,
40 | BsGit
41 | } from "react-icons/bs";
42 | import { GiArchiveResearch, GiArtificialIntelligence } from "react-icons/gi";
43 | import { FcElectronics } from "react-icons/fc";
44 | import { SiTailwindcss } from "react-icons/si";
45 | import {
46 | SiVite,
47 | SiRabbitmq,
48 | SiKeycloak,
49 | SiNginx,
50 | SiApache,
51 | SiLinux,
52 | SiGitlab,
53 | SiGithubactions,
54 | SiMailchimp,
55 | SiSpringboot,
56 | SiMongodb,
57 | SiRedis,
58 | SiPostgresql,
59 | SiMysql,
60 | SiFastapi,
61 | SiJest,
62 | SiSelenium,
63 | SiPlaywright,
64 | SiHtmx,
65 | SiC,
66 | SiLangchain,
67 | SiFirebase,
68 | SiSupabase,
69 | SiWebpack,
70 | SiMarkdown
71 | } from "react-icons/si";
72 | import { BsBox } from "react-icons/bs";
73 |
74 | export const links = [
75 | { text: "Home", path: "/" },
76 | { text: "About", path: "/about" },
77 | { text: "Skills", path: "/skills" },
78 | { text: "Projects", path: "/projects" },
79 | { text: "Experience", path: "/experience" },
80 | { text: "Blogs", path: "/blogs" },
81 | { text: "Contact", path: "/contact" }
82 | ];
83 |
84 | export const interestsData = [
85 | {
86 | interest: "Software Engineering",
87 | icon: BsCodeSlash,
88 | },
89 | {
90 | interest: "Tech Blog",
91 | icon: FaHashnode,
92 | },
93 | {
94 | interest: "Internet of Things",
95 | icon: FcElectronics,
96 | },
97 | {
98 | interest: "Market Research",
99 | icon: GiArchiveResearch,
100 | },
101 | {
102 | interest: "Visualization",
103 | icon: BsFileBarGraph,
104 | },
105 | {
106 | interest: "Software Development",
107 | icon: AiFillCode,
108 | },
109 | {
110 | interest: "Robotics",
111 | icon: BsRobot,
112 | },
113 | {
114 | interest: "Web Scraping",
115 | icon: BsGlobe,
116 | },
117 | ];
118 |
119 | export const skillsData = [
120 | {
121 | category: "Programming Languages",
122 | skills: [
123 | {
124 | name: "JavaScript",
125 | icon: TbBrandJavascript,
126 | color: "#F7DF1E"
127 | },
128 | {
129 | name: "TypeScript",
130 | icon: TbBrandTypescript,
131 | color: "#3178C6"
132 | },
133 | {
134 | name: "Python",
135 | icon: FaPython,
136 | color: "#3776AB"
137 | },
138 | {
139 | name: "C++",
140 | icon: TbBrandCpp,
141 | color: "#00599C"
142 | },
143 | {
144 | name: "C",
145 | icon: SiC,
146 | color: "#A8B9CC"
147 | },
148 | {
149 | name: "Java",
150 | icon: FaJava,
151 | color: "#007396"
152 | },
153 | {
154 | name: "Bash",
155 | icon: SiGnubash,
156 | color: "#4EAA25"
157 | },
158 | ]
159 | },
160 | {
161 | category: "JavaScript Frameworks",
162 | skills: [
163 | {
164 | name: "React.js",
165 | icon: FaReact,
166 | color: "#61DAFB"
167 | },
168 | {
169 | name: "Next.js",
170 | icon: SiNextdotjs,
171 | color: "#000000"
172 | },
173 | {
174 | name: "Redux",
175 | icon: TbBrandRedux,
176 | color: "#764ABC"
177 | },
178 | {
179 | name: "Node.js",
180 | icon: FaNodeJs,
181 | color: "#339933"
182 | },
183 | {
184 | name: "Express.js",
185 | icon: SiExpress,
186 | color: "#000000"
187 | },
188 | {
189 | name: "Spring Boot",
190 | icon: SiSpringboot,
191 | color: "#6DB33F"
192 | },
193 | {
194 | name: "FastAPI",
195 | icon: SiFastapi,
196 | color: "#009688"
197 | },
198 | ]
199 | },
200 | {
201 | category: "Version Control Systems",
202 | skills: [
203 | {
204 | name: "Git",
205 | icon: BsGit,
206 | color: "#F05032"
207 | },
208 | {
209 | name: "GitLab",
210 | icon: SiGitlab,
211 | color: "#FC6D26"
212 | },
213 | {
214 | name: "GitHub Actions",
215 | icon: SiGithubactions,
216 | color: "#2088FF"
217 | },
218 | ]
219 | },
220 | {
221 | category: "Web Technologies",
222 | skills: [
223 | {
224 | name: "HTML5",
225 | icon: FaHtml5,
226 | color: "#E34F26"
227 | },
228 | {
229 | name: "CSS3",
230 | icon: FaCss3,
231 | color: "#1572B6"
232 | },
233 | {
234 | name: "SASS",
235 | icon: FaSass,
236 | color: "#CC6699"
237 | },
238 | {
239 | name: "Bootstrap",
240 | icon: TbBrandBootstrap,
241 | color: "#7952B3"
242 | },
243 | {
244 | name: "Tailwind CSS",
245 | icon: SiTailwindcss,
246 | color: "#06B6D4"
247 | },
248 | {
249 | name: "jQuery",
250 | icon: BiLogoJquery,
251 | color: "#0769AD"
252 | },
253 | {
254 | name: "Vite",
255 | icon: SiVite,
256 | color: "#646CFF"
257 | },
258 | {
259 | name: "Parcel",
260 | icon: BsBox,
261 | color: "#2D8CFF"
262 | },
263 | {
264 | name: "Webpack",
265 | icon: SiWebpack,
266 | color: "#8DD6F9"
267 | },
268 | {
269 | name: "PugJS",
270 | icon: SiPug,
271 | color: "#A86454"
272 | },
273 | {
274 | name: "MJML",
275 | icon: SiMailchimp,
276 | color: "#FF0080"
277 | },
278 | {
279 | name: "HTMX",
280 | icon: SiHtmx,
281 | color: "#1A1A1A"
282 | },
283 | {
284 | name: "RESTful APIs",
285 | icon: SiExpress,
286 | color: "#000000"
287 | },
288 | {
289 | name: "Postman",
290 | icon: SiPostman,
291 | color: "#FF6C37"
292 | },
293 | {
294 | name: "Markdown",
295 | icon: SiMarkdown,
296 | color: "#000000"
297 | },
298 | ]
299 | },
300 | {
301 | category: "Databases",
302 | skills: [
303 | {
304 | name: "PostgreSQL",
305 | icon: SiPostgresql,
306 | color: "#336791"
307 | },
308 | {
309 | name: "MongoDB",
310 | icon: SiMongodb,
311 | color: "#47A248"
312 | },
313 | {
314 | name: "Redis",
315 | icon: SiRedis,
316 | color: "#DC382D"
317 | },
318 | {
319 | name: "MySQL",
320 | icon: SiMysql,
321 | color: "#4479A1"
322 | },
323 | {
324 | name: "Firebase",
325 | icon: SiFirebase,
326 | color: "#FFCA28"
327 | },
328 | {
329 | name: "Supabase",
330 | icon: SiSupabase,
331 | color: "#3ECF8E"
332 | },
333 | ]
334 | },
335 | {
336 | category: "Testing Tools",
337 | skills: [
338 | {
339 | name: "Jest",
340 | icon: SiJest,
341 | color: "#C21325"
342 | },
343 | {
344 | name: "Selenium",
345 | icon: SiSelenium,
346 | color: "#43B02A"
347 | },
348 | {
349 | name: "Playwright",
350 | icon: SiPlaywright,
351 | color: "#2EAD33"
352 | },
353 | ]
354 | },
355 | {
356 | category: "AI & Development Tools",
357 | skills: [
358 | {
359 | name: "RAG",
360 | icon: GiArtificialIntelligence,
361 | color: "#FF6B6B"
362 | },
363 | {
364 | name: "LangChain",
365 | icon: BsRobot,
366 | color: "#00A67E"
367 | },
368 | {
369 | name: "Prompt Engineering",
370 | icon: GiArtificialIntelligence,
371 | color: "#FF6B6B"
372 | },
373 | {
374 | name: "Docker",
375 | icon: FaDocker,
376 | color: "#2496ED"
377 | },
378 | {
379 | name: "RabbitMQ",
380 | icon: SiRabbitmq,
381 | color: "#FF6600"
382 | },
383 | {
384 | name: "Keycloak",
385 | icon: SiKeycloak,
386 | color: "#EDEDED"
387 | },
388 | {
389 | name: "Nginx",
390 | icon: SiNginx,
391 | color: "#009639"
392 | },
393 | {
394 | name: "Apache",
395 | icon: SiApache,
396 | color: "#D22128"
397 | },
398 | {
399 | name: "Linux",
400 | icon: SiLinux,
401 | color: "#FCC624"
402 | },
403 | ]
404 | }
405 | ];
406 |
407 | export const workData = [
408 | {
409 | company: "1Digitalstack.ai",
410 | companyImg: "1ds.jpg",
411 | roles: [
412 | {
413 | designation: "Software Engineer 3",
414 | duration: "April 2025 - Present",
415 | description: (
416 | <>
417 |
418 |
419 | Spearheaded the design and development of a chatbot using Retrieval-Augmented Generation (RAG) for actionable insights in e-commerce.
420 |
421 |
422 | Built frontend, backend, and integrated with RAG-based APIs to enable analytics and automate actions.
423 |
424 |
425 | >
426 | ),
427 | },
428 | {
429 | designation: "Software Engineer 2",
430 | duration: "April 2024 - March 2025",
431 | description: (
432 | <>
433 |
434 |
435 | Developed a self-serve email platform for ecommerce companies with a custom drag-and-drop editor.
436 |
437 |
438 | Implemented scheduling functionality for dashboard updates and performance reports.
439 |
440 |
441 | Collaborated with cross-functional teams to ensure seamless integration and user-friendly experience.
442 |
443 |
444 | >
445 | ),
446 | },
447 | {
448 | designation: "Software Engineer 1",
449 | duration: "March 2022 - March 2024",
450 | description: (
451 | <>
452 |
453 |
454 | Worked on Reviniti, a bid manager and analytics product for players operating in e-commerce platforms.
455 |
456 |
457 | Solely migrated the old codebase from PugJS to React-TypeScript, implementing efficient state management, authentication, reusable components and layouts.
458 |
459 |
460 | Key responsibilities included:
461 |
462 | Developing new features and REST APIs
463 | Code refactoring and performance optimization
464 | Bug fixing and product testing
465 | Writing data acquisition scripts
466 | Contributing to product scalability
467 |
468 |
469 |
470 | >
471 | ),
472 | }
473 | ]
474 | },
475 | {
476 | company: "Fact.MR",
477 | companyImg: "fmr.svg",
478 | roles: [
479 | {
480 | designation: "Associate Consultant Level-1",
481 | duration: "December 2020 - July 2021",
482 | description: (
483 | <>
484 |
485 |
486 | Developed and implemented automated data collection systems using Python, resulting in 70% faster market analysis processes. Created dynamic PowerBI dashboards that provided real-time market insights, leading to a 40% increase in client engagement and a 25% improvement in report delivery times.
487 |
488 |
489 | >
490 | ),
491 | }
492 | ]
493 | },
494 | ];
495 |
496 | export const projectsData = [
497 | {
498 | type: "WEB-APP",
499 | title: "Movie Magnet",
500 | image: "movie-magnet",
501 | link: "https://movie-magnet-smoky.vercel.app/",
502 | source: "https://github.com/vaheedsk36/movie-magnet",
503 | },
504 | {
505 | type: "WEB-APP",
506 | title: "Portfolio Website",
507 | image: "portfolio-website",
508 | link: null,
509 | source: "https://github.com/vaheedsk36/portfolio-website-nextjs",
510 | },
511 | {
512 | type: "WEB-APP",
513 | title: "Weather App",
514 | image: "weather-app",
515 | link: "https://vaheedsk36.github.io/weather-app/",
516 | source: "https://github.com/vaheedsk36/weather-app",
517 | },
518 | {
519 | type: "WEB-APP",
520 | title: "Landing Page",
521 | image: "landing-page",
522 | link: "https://vaheedsk36.github.io/demo-frontend-bootcamp",
523 | source: "https://github.com/vaheedsk36/demo-frontend-bootcamp",
524 | },
525 | {
526 | type: "WEB-APP",
527 | title: "Guess Game",
528 | image: "guess-game",
529 | link: "https://vaheedsk36.github.io/guess-my-number",
530 | source: "https://github.com/vaheedsk36/guess-my-number",
531 | },
532 | {
533 | type: "WEB-APP",
534 | title: "Notes App",
535 | image: "react-notes-app",
536 | link: "https://vaheedsk36.github.io/react-notes-app/",
537 | source: "https://github.com/vaheedsk36/react-notes-app",
538 | },
539 | {
540 | type: "WEB-APP",
541 | title: "Dice Multiplayer",
542 | image: "dice-multiplayer",
543 | link: "https://vaheedsk36.github.io/dice-multiplayer",
544 | source: "https://github.com/vaheedsk36/dice-multiplayer",
545 | },
546 | {
547 | type: "PROJECT",
548 | title: "Snake Game",
549 | image: "snake-game",
550 | link: "https://vaheedsk36.github.io/Snake-game",
551 | source: "",
552 | },
553 | {
554 | type: "PROJECT",
555 | title: "Delta Assistant",
556 | image: "delta-assistant",
557 | link: "",
558 | source: "https://github.com/vaheedsk36/Delta-Desktop-Virtual-Assistant",
559 | },
560 | {
561 | type: "WEB-APP",
562 | title: "Text Utility App",
563 | image: "text-utility-app",
564 | link: "https://vaheedsk36.github.io/text-utility-app/",
565 | source: "https://github.com/vaheedsk36/text-utility-app",
566 | },
567 | ];
568 |
569 |
570 | export const socialMediaLinks = [
571 | {
572 | href: "https://github.com/vaheedsk36",
573 | icon: FaGithub,
574 | backgroundColor: "gray.700",
575 | hoverColor: "gray.600",
576 | },
577 | {
578 | href: "https://www.instagram.com/codersk36/",
579 | icon: FaInstagram,
580 | backgroundColor: "social.instagram",
581 | hoverColor: "social.instagramHover",
582 | },
583 | {
584 | href: "https://www.linkedin.com/in/sk36/",
585 | icon: FaLinkedin,
586 | backgroundColor: "social.linkedin",
587 | hoverColor: "social.linkedinHover",
588 | },
589 | {
590 | href: "https://twitter.com/codersk36",
591 | icon: FaXTwitter,
592 | backgroundColor: "gray.700",
593 | hoverColor: "gray.600",
594 | },
595 | {
596 | href: "https://codersk36.hashnode.dev/",
597 | icon: FaHashnode,
598 | backgroundColor: "social.hashnode",
599 | hoverColor: "social.hashnodeHover",
600 | },
601 | {
602 | href: "https://medium.com/@vaheedsk36",
603 | icon: FaMediumM,
604 | backgroundColor: "gray.700",
605 | hoverColor: "gray.600",
606 | }
607 | ];
608 |
609 | export const query = `
610 | query Publication($after: String) {
611 | publication(host: "codersk36.hashnode.dev") {
612 | posts(first: 20, after: $after) {
613 | totalDocuments
614 | pageInfo {
615 | hasNextPage
616 | endCursor
617 | }
618 | edges {
619 | node {
620 | title
621 | brief
622 | slug
623 | publishedAt
624 | coverImage {
625 | url
626 | }
627 | }
628 | }
629 | }
630 | }
631 | }
632 |
633 | `;
634 |
635 |
636 |
--------------------------------------------------------------------------------