├── .eslintrc.json
├── .github
└── workflows
│ └── nextjs.yml
├── .gitignore
├── .vscode
└── settings.json
├── CNAME
├── README.md
├── next.config.mjs
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
├── favicon.ico
├── networking-1.png
├── networking-10.png
├── networking-11.png
├── networking-12.png
├── networking-13.png
├── networking-14.png
├── networking-2.png
├── networking-3.png
├── networking-4.png
├── networking-5.png
├── networking-6.png
├── networking-7.png
├── networking-8.png
├── networking-9.png
├── next.svg
├── project-1.png
├── project-2.png
├── project-3.png
├── project-4.gif
├── project-5.png
├── project-6.png
├── project-7.png
├── project-8.png
├── sponsor-icon.png
└── vercel.svg
├── src
├── app
│ ├── globals.css
│ ├── layout.tsx
│ ├── page.tsx
│ └── pages
│ │ ├── _document.js
│ │ ├── about.tsx
│ │ ├── articles.tsx
│ │ ├── button.tsx
│ │ ├── contact.tsx
│ │ ├── experience.tsx
│ │ ├── homescreen.tsx
│ │ ├── networking.tsx
│ │ └── projects.tsx
└── components
│ ├── Tooltip.tsx
│ ├── footer.tsx
│ ├── ui
│ ├── 3d-card.tsx.tsx
│ ├── 3d-pin.tsx
│ ├── flip-words.tsx
│ ├── floating-dock.tsx
│ ├── parallax-scroll.tsx
│ ├── sparkles.tsx
│ ├── tailwindcss-buttons.tsx
│ ├── timeline.tsx
│ └── tracing-beam.tsx
│ └── utils
│ └── cn.ts
├── tailwind.config.ts
├── tsconfig.json
└── yarn.lock
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "next/core-web-vitals"
3 | }
4 |
--------------------------------------------------------------------------------
/.github/workflows/nextjs.yml:
--------------------------------------------------------------------------------
1 | # Sample workflow for building and deploying a Next.js site to GitHub Pages
2 | name: Deploy Next.js site to Pages
3 |
4 | on:
5 | # Runs on pushes targeting the default branch
6 | push:
7 | branches: ["master"]
8 |
9 | # Allows you to run this workflow manually from the Actions tab
10 | workflow_dispatch:
11 |
12 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
13 | permissions:
14 | contents: read
15 | pages: write
16 | id-token: write
17 |
18 | concurrency:
19 | group: "pages"
20 | cancel-in-progress: false
21 |
22 | jobs:
23 | build:
24 | runs-on: ubuntu-latest
25 | steps:
26 | - name: Checkout
27 | uses: actions/checkout@v4
28 |
29 | - name: Detect package manager
30 | id: detect-package-manager
31 | run: |
32 | if [ -f "${{ github.workspace }}/yarn.lock" ]; then
33 | echo "manager=yarn" >> $GITHUB_OUTPUT
34 | echo "command=install" >> $GITHUB_OUTPUT
35 | echo "runner=yarn" >> $GITHUB_OUTPUT
36 | exit 0
37 | elif [ -f "${{ github.workspace }}/package.json" ]; then
38 | echo "manager=npm" >> $GITHUB_OUTPUT
39 | echo "command=ci" >> $GITHUB_OUTPUT
40 | echo "runner=npx --no-install" >> $GITHUB_OUTPUT
41 | exit 0
42 | else
43 | echo "Unable to determine package manager"
44 | exit 1
45 | fi
46 |
47 | - name: Setup Node
48 | uses: actions/setup-node@v4
49 | with:
50 | node-version: "20"
51 | cache: ${{ steps.detect-package-manager.outputs.manager }}
52 |
53 | - name: Install dependencies
54 | run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }}
55 |
56 | - name: Build with Next.js
57 | run: ${{ steps.detect-package-manager.outputs.runner }} next build
58 |
59 | - name: Upload artifact
60 | uses: actions/upload-pages-artifact@v3
61 | with:
62 | path: ./out
63 |
64 | deploy:
65 | environment:
66 | name: github-pages
67 | url: ${{ steps.deployment.outputs.page_url }}
68 | runs-on: ubuntu-latest
69 | needs: build
70 | steps:
71 | - name: Deploy to GitHub Pages
72 | id: deployment
73 | uses: actions/deploy-pages@v4
74 |
--------------------------------------------------------------------------------
/.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 | .yarn/install-state.gz
8 | firebase-cred.js
9 | .env
10 |
11 | # testing
12 | /coverage
13 |
14 | # next.js
15 | /.next/
16 | /out/
17 |
18 | # production
19 | /build
20 |
21 | # misc
22 | .DS_Store
23 | *.pem
24 |
25 | # debug
26 | npm-debug.log*
27 | yarn-debug.log*
28 | yarn-error.log*
29 |
30 | # local env files
31 | .env*.local
32 |
33 | # vercel
34 | .vercel
35 |
36 | # typescript
37 | *.tsbuildinfo
38 | next-env.d.ts
39 | .qodo
40 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "cSpell.words": [
3 | "tsparticles"
4 | ]
5 | }
--------------------------------------------------------------------------------
/CNAME:
--------------------------------------------------------------------------------
1 | lassiecoder.com
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Portfolio
2 |
3 | Hi there, I'm **lassiecoder**! 👋
4 | This is my personal portfolio template built using Next.js and Tailwind CSS with smooth animations powered by Framer Motion.
5 |
6 | ## Author
7 |
8 | **Priyanka Sharma**
9 |
10 | - Email: sharmapriyanka84510@gmail.com
11 |
12 | ## License
13 |
14 | This project is licensed under the MIT License.
15 |
16 | ## Installation
17 |
18 | 1. Clone the repository:
19 |
20 | ```bash
21 | git clone https://github.com/yourusername/portfolio.git
22 | cd portfolio
23 | ```
24 |
25 | 2. Install the dependencies:
26 |
27 | ```bash
28 | npm install
29 | ```
30 |
31 | ## Usage
32 |
33 | ### Development
34 |
35 | To start the development server:
36 |
37 | ```bash
38 | npm run dev
39 | ```
40 |
41 | ## Scripts
42 |
43 | - `dev`: Starts the development server.
44 | - `build`: Builds the project for production.
45 | - `start`: Starts the production server.
46 | - `lint`: Runs ESLint.
47 | - `predeploy`: Prepares the project for deployment.
48 | - `deploy`: Builds and deploys the project.
49 |
50 | ## Dependencies
51 |
52 | - **@tabler/icons-react**: ^3.1.0
53 | - **@tsparticles/engine**: ^3.3.0
54 | - **@tsparticles/react**: ^3.0.0
55 | - **@tsparticles/slim**: ^3.3.0
56 | - **clsx**: ^2.1.0
57 | - **framer-motion**: ^11.0.25
58 | - **gh-pages**: ^6.1.1
59 | - **next**: ^14.1.4
60 | - **react**: ^18
61 | - **react-dom**: ^18
62 | - **react-element-to-jsx-string**: ^15.0.0
63 | - **react-ga4**: ^2.1.0
64 | - **react-icons**: ^5.0.1
65 | - **sonner**: ^1.4.41
66 | - **tailwind-merge**: ^2.2.2
67 | - **typewriter-effect**: ^2.21.0
68 |
69 | ## Dev Dependencies
70 |
71 | - **@types/node**: ^20
72 | - **@types/react**: ^18
73 | - **@types/react-dom**: ^18
74 | - **autoprefixer**: ^10.0.1
75 | - **eslint**: ^8
76 | - **eslint-config-next**: 14.1.4
77 | - **postcss**: ^8
78 | - **tailwindcss**: ^3.3.0
79 | - **typescript**: ^5
80 |
81 | ## Deployment
82 |
83 | 1. Open your terminal in the project directory.
84 |
85 | 2. Run the following command to build the project:
86 |
87 | ```bash
88 | npm run build
89 | ```
90 |
91 | 3. Stage the Changes
92 |
93 | ```bash
94 | git add .
95 | ```
96 |
97 | 4. Commit the changes
98 |
99 | ```bash
100 | git commit -m "COMMIT_MESSAGE"
101 | ```
102 |
103 | 5. Push the changes to your GitHub repository
104 |
105 | ```bash
106 | git push origin master
107 | ```
108 |
109 | ### NOTE: Monitor GitHub Actions
110 |
111 | 1. Navigate to the Actions tab of your GitHub repository.
112 | 2. Check for any running or completed workflows.
113 | 3. Ensure the deployment workflow runs successfully.
114 |
115 | ## Contributing
116 |
117 | Feel free to submit issues or pull requests.
118 |
119 | ## Preview
120 |
121 | 
122 |
123 | ## Contact
124 |
125 | For any inquiries, please contact me at lassiecoder@gmail.com.
126 |
--------------------------------------------------------------------------------
/next.config.mjs:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | output: "export",
4 | images: {
5 | unoptimized: true,
6 | domains: [
7 | "github.com",
8 | "user-images.githubusercontent.com",
9 | "assets.aceternity.com"
10 | ],
11 | remotePatterns: [
12 | {
13 | protocol: "https",
14 | hostname: "github.com",
15 | pathname: "/lassiecoder/**"
16 | }
17 | ]
18 | }
19 | };
20 |
21 | export default nextConfig;
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "portfolio",
3 | "version": "0.1.0",
4 | "description": "Personal portfolio template built using NextJS and Tailwind",
5 | "author": {
6 | "name": "priyanka sharma",
7 | "email": "sharmapriyanka84510@gmail.com"
8 | },
9 | "license": "MIT",
10 | "private": true,
11 | "scripts": {
12 | "dev": "next dev",
13 | "build": "next build",
14 | "start": "next start",
15 | "lint": "next lint",
16 | "predeploy": "npm run build",
17 | "deploy": "npm run build && gh-pages -d build"
18 | },
19 | "dependencies": {
20 | "@tabler/icons-react": "^3.24.0",
21 | "@tsparticles/engine": "^3.3.0",
22 | "@tsparticles/react": "^3.0.0",
23 | "@tsparticles/slim": "^3.3.0",
24 | "clsx": "^2.1.1",
25 | "framer-motion": "^11.13.1",
26 | "gh-pages": "^6.1.1",
27 | "next": "^15.0.0",
28 | "react": "^18.3.1",
29 | "react-dom": "^18.3.1",
30 | "react-element-to-jsx-string": "^15.0.0",
31 | "react-ga4": "^2.1.0",
32 | "react-icons": "^5.0.1",
33 | "react-social-media-embed": "^2.5.17",
34 | "sonner": "^1.4.41",
35 | "tailwind-merge": "^2.5.5",
36 | "typewriter-effect": "^2.21.0"
37 | },
38 | "devDependencies": {
39 | "@types/node": "22.13.10",
40 | "@types/react": "19.0.10",
41 | "@types/react-dom": "^18",
42 | "autoprefixer": "^10.0.1",
43 | "eslint": "^8",
44 | "eslint-config-next": "14.1.4",
45 | "postcss": "^8",
46 | "tailwindcss": "^3.3.0",
47 | "typescript": "5.8.2"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/favicon.ico
--------------------------------------------------------------------------------
/public/networking-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/networking-1.png
--------------------------------------------------------------------------------
/public/networking-10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/networking-10.png
--------------------------------------------------------------------------------
/public/networking-11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/networking-11.png
--------------------------------------------------------------------------------
/public/networking-12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/networking-12.png
--------------------------------------------------------------------------------
/public/networking-13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/networking-13.png
--------------------------------------------------------------------------------
/public/networking-14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/networking-14.png
--------------------------------------------------------------------------------
/public/networking-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/networking-2.png
--------------------------------------------------------------------------------
/public/networking-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/networking-3.png
--------------------------------------------------------------------------------
/public/networking-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/networking-4.png
--------------------------------------------------------------------------------
/public/networking-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/networking-5.png
--------------------------------------------------------------------------------
/public/networking-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/networking-6.png
--------------------------------------------------------------------------------
/public/networking-7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/networking-7.png
--------------------------------------------------------------------------------
/public/networking-8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/networking-8.png
--------------------------------------------------------------------------------
/public/networking-9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/networking-9.png
--------------------------------------------------------------------------------
/public/next.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/project-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/project-1.png
--------------------------------------------------------------------------------
/public/project-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/project-2.png
--------------------------------------------------------------------------------
/public/project-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/project-3.png
--------------------------------------------------------------------------------
/public/project-4.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/project-4.gif
--------------------------------------------------------------------------------
/public/project-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/project-5.png
--------------------------------------------------------------------------------
/public/project-6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/project-6.png
--------------------------------------------------------------------------------
/public/project-7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/project-7.png
--------------------------------------------------------------------------------
/public/project-8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/project-8.png
--------------------------------------------------------------------------------
/public/sponsor-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lassiecoder/portfolio/e229a6a2fa4665f8569e9439af514cc1c2e5aec1/public/sponsor-icon.png
--------------------------------------------------------------------------------
/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | :root {
6 | --foreground-rgb: 0, 0, 0;
7 | --background-start-rgb: 214, 219, 220;
8 | --background-end-rgb: 255, 255, 255;
9 | }
10 |
11 | @media (prefers-color-scheme: dark) {
12 | :root {
13 | --foreground-rgb: 255, 255, 255;
14 | --background-start-rgb: 0, 0, 0;
15 | --background-end-rgb: 0, 0, 0;
16 | }
17 | }
18 |
19 | body {
20 | color: rgb(var(--foreground-rgb));
21 | background: linear-gradient(
22 | to bottom,
23 | transparent,
24 | rgb(var(--background-end-rgb))
25 | )
26 | rgb(var(--background-start-rgb));
27 | }
28 |
29 | @layer utilities {
30 | .text-balance {
31 | text-wrap: balance;
32 | }
33 | }
34 |
35 | @keyframes spin-slow {
36 | 0% {
37 | transform: rotate(0deg);
38 | }
39 | 100% {
40 | transform: rotate(360deg);
41 | }
42 | }
43 | .animate-spin-slow {
44 | animation: spin-slow 10s linear infinite;
45 | }
46 |
--------------------------------------------------------------------------------
/src/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import type { Metadata } from "next";
2 | import { Montserrat } from "next/font/google";
3 | import "./globals.css";
4 | import {} from "next/font/google";
5 |
6 | export const metadata: Metadata = {
7 | title:
8 | "Portfolio | Priyanka Sharma (lassiecoder) | Mobile & Web app developer",
9 | description:
10 | "Crafting compelling narratives through design, merging creativity with functionality seamlessly."
11 | };
12 |
13 | const montserrat = Montserrat({
14 | subsets: ["latin"],
15 | display: "swap",
16 | variable: "--font-montserrat"
17 | });
18 |
19 | export default function RootLayout({
20 | children
21 | }: Readonly<{
22 | children: React.ReactNode;
23 | }>) {
24 | return (
25 |
26 |
{children}
27 |
28 | );
29 | }
30 |
--------------------------------------------------------------------------------
/src/app/page.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import HomeScreen from "@/app/pages/homescreen";
4 | import { Article } from "@/app/pages/articles";
5 | import ThreeDCard from "@/app/pages/projects";
6 | import About from "@/app/pages/about";
7 | import ContactForm from "./pages/contact";
8 | // import Navbar from "@/components/navbar";
9 |
10 | import ReactGA from "react-ga4";
11 | import { useEffect } from "react";
12 | import { Experience } from "./pages/experience";
13 | import Networking from "./pages/networking";
14 |
15 | export default function Home() {
16 | useEffect(() => {
17 | ReactGA.initialize("G-PYQ50G2GWN");
18 | }, []);
19 |
20 | return (
21 |
21 |
22 |
23 | {/* */}
24 |
25 |
26 |
30 | I'm open for
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | I appreciate your interest in connecting with me. I'm excited to
42 | explore new opportunities ,{" "}
43 | receive feedback ,{" "}
44 | collaborate on projects , and
45 | broaden my network.
46 |
47 |
48 | For any specific questions or comments, please don't hesitate to
49 | contact me directly at
50 |
55 | lassiecoder@gmail.com
56 |
57 | . I strive to respond to all messages within{" "}
58 | 24 hours , although it may take a
59 | bit longer during busy periods.{" "}
60 |
61 | If you prefer social media, you can also find me on{" "}
62 |
Instagram at
63 |
68 | @lassiecoder
69 |
70 | .
71 |
72 |
77 |
85 |
86 |
87 | Always be caffeinated! | © Priyanka Sharma (lassiecoder)
88 |
89 |
90 | );
91 | };
92 |
93 | export default ContactForm;
94 |
--------------------------------------------------------------------------------
/src/app/pages/experience.tsx:
--------------------------------------------------------------------------------
1 | import Image from "next/image";
2 | import React, { useEffect, useState } from "react";
3 | import { Timeline } from "@/components/ui/timeline";
4 |
5 | export function Experience() {
6 | const [isSmallScreen, setIsSmallScreen] = useState(false);
7 |
8 | useEffect(() => {
9 | const handleResize = () => {
10 | setIsSmallScreen(window.innerWidth <= 770);
11 | };
12 |
13 | // Check screen size on initial render
14 | handleResize();
15 |
16 | // Add event listener for window resize
17 | window.addEventListener("resize", handleResize);
18 |
19 | // Cleanup the event listener on component unmount
20 | return () => window.removeEventListener("resize", handleResize);
21 | }, []);
22 | const data = [
23 | {
24 | title: (
25 |
31 | ),
32 | duration: "2023 – Present",
33 | smallScreenLogo: (
34 |
40 | ),
41 | content: (
42 |
43 |
44 |
45 |
46 | Software Developer
47 |
48 |
49 | {/* Show only if screen size is <= 770px */}
50 | {isSmallScreen && (
51 |
52 | The Adecco Group
53 | (May 2023 – Present)
54 |
55 | )}
56 |
57 | {/* Show only if screen size is > 770px */}
58 | {!isSmallScreen && (
59 |
60 | (May 2023 – Present)
61 |
62 | )}
63 |
64 |
65 |
66 | The Adecco Group is a global{" "}
67 | HR solutions company that
68 | provides workforce solutions ,
69 | including recruitment ,{" "}
70 | temporary staffing ,{" "}
71 | career transition ,{" "}
72 | talent development , and{" "}
73 | outsourcing services to
74 | businesses across various industries.
75 |
76 |
77 |
78 | At Adecco Group , I
79 | contribute to the development of the{" "}
80 | Adecco India app , which is
81 | utilized by top companies for staffing solutions.
82 |
83 | I also work on the{" "}
84 | global web app , ensuring
85 | it meets diverse needs across various regions. My expertise
86 | includes using{" "}
87 | React Native and{" "}
88 | React.js to build
89 | efficient, user-friendly applications.
90 |
91 |
92 |
93 | Additionally, I have developed a{" "}
94 | white-label solution {" "}
95 | designed to streamline the candidate onboarding process,
96 | enhancing user experience and operational efficiency. This
97 | experience has honed my skills in creating scalable applications
98 | that facilitate better hiring and onboarding practices globally.
99 |
100 |
101 |
102 |
103 | )
104 | },
105 | {
106 | title: (
107 |
113 | ),
114 | duration: "2023 – Present",
115 | smallScreenLogo: (
116 |
122 | ),
123 | content: (
124 |
125 |
126 |
127 |
128 | Mobile Application Developer
129 |
130 | {/*
131 | (May 2022 – May 2023)
132 |
*/}
133 | {isSmallScreen && (
134 |
135 | Torum
136 | (May 2022 – May 2023)
137 |
138 | )}
139 |
140 | {/* Show only if screen size is > 770px */}
141 | {!isSmallScreen && (
142 |
143 | (May 2022 – May 2023)
144 |
145 | )}
146 |
147 |
148 |
149 | Torum is a
150 | cryptocurrency-focused{" "}
151 | social media platform that
152 | connects enthusiasts ,{" "}
153 | investors , and{" "}
154 | developers , allowing them to
155 | share insights , build{" "}
156 | communities , and earn{" "}
157 | rewards through content
158 | creation. It also includes features like a{" "}
159 | marketplace for buying and
160 | selling crypto and{" "}
161 | educational resources .
162 |
163 |
164 |
165 | At Torum , I significantly
166 | enhanced user engagement by implementing effective
167 | in-app and{" "}
168 | push notifications ,
169 | utilizing deep linking {" "}
170 | for smooth user redirection. I designed robust and user-friendly
171 | components, rigorously testing them to ensure scalability for
172 | future feature expansions.
173 |
174 |
175 | I also established streamlined{" "}
176 | deployment processes
177 | through the{" "}
178 | Google Play Console ,
179 | facilitating seamless alpha and beta app distribution.
180 |
{" "}
181 |
182 | To further{" "}
183 |
184 | optimize mobile app performance
185 | {" "}
186 | and address slowness issues, I implemented several strategies. I
187 | improved the app's responsiveness by utilizing{" "}
188 | lazy loading techniques to
189 | load components only when needed, reducing initial load time. I
190 | also optimized images and other assets for{" "}
191 | faster rendering , ensuring
192 | that they are appropriately compressed and sized for mobile
193 | devices.
194 |
195 |
196 | Additionally, I created
197 | comprehensive guidelines for mobile app{" "}
198 | version control ,{" "}
199 | commits , and{" "}
200 | pull request procedures ,
201 | providing essential support to my fellow developers. This
202 | approach not only{" "}
203 |
204 | improved operational efficiency
205 | {" "}
206 | but also fostered a collaborative development environment.
207 |
208 |
209 |
210 |
211 | )
212 | },
213 | {
214 | title: (
215 |
221 | ),
222 | smallScreenLogo: (
223 |
229 | ),
230 | content: (
231 |
232 |
233 |
234 |
235 | Product Engineer
236 |
237 | {/*
238 | (Aug 2020 - May 2022)
239 |
*/}
240 | {isSmallScreen && (
241 |
242 | EduFund
243 | (Aug 2020 - May 2022)
244 |
245 | )}
246 |
247 | {/* Show only if screen size is > 770px */}
248 | {!isSmallScreen && (
249 |
250 | (Aug 2020 - May 2022)
251 |
252 | )}
253 |
254 |
255 |
256 |
EduFund is India's first
257 | dedicated{" "}
258 |
education savings platform ,
259 | helping parents plan financially for their children's higher
260 | education through
investment ,{" "}
261 |
cost discovery , and{" "}
262 |
academic counseling .
263 |
264 | The app offers tools to estimate future college expenses, invest
265 | in various asset classes, secure education loans, and access
266 | academic guidance.
267 |
268 |
269 |
270 |
271 | At
EduFund , I led the
272 | implementation of{" "}
273 |
KYC verification processes {" "}
274 | for investment account creation in{" "}
275 |
India and the{" "}
276 |
United States , streamlining
277 | the onboarding experience for non-KYC users. By leveraging
278 | third-party tools, I ensured secure data access through advanced
279 | biometric features such as{" "}
280 |
facial recognition and{" "}
281 |
fingerprint scanning .
282 |
283 | To optimize user tracking and enhance marketing strategies, I
284 | integrated Firebase for
285 | comprehensive monitoring of user activities, allowing us to
286 | refine targeted marketing efforts based on demographic data.
287 | This integration of{" "}
288 | push notifications resulted
289 | in a remarkable 47% {" "}
290 | increase in new user engagement.
291 |
292 |
293 | I also streamlined app building and deployment workflows by
294 | seamlessly integrating{" "}
295 | Fastlane , a third-party
296 | tool that automated our deployment processes. Additionally, I
297 | played a pivotal role in developing a{" "}
298 | white-label solution for{" "}
299 | ICICI Bank , leveraging{" "}
300 | Next.js technology to
301 | enhance our offerings. This multifaceted approach not only
302 | improved operational efficiency but also contributed to the
303 | overall growth of the platform.
304 |
305 |
306 |
307 |
308 | )
309 | }
310 | ];
311 | return (
312 |
313 |
314 |
315 | Experience
316 |
317 |
318 |
319 |
320 | );
321 | }
322 |
--------------------------------------------------------------------------------
/src/app/pages/homescreen.tsx:
--------------------------------------------------------------------------------
1 | import Footer from "@/components/footer";
2 | import {
3 | IconBrandGithub,
4 | IconBrandX,
5 | IconExchange,
6 | IconHome,
7 | IconNewSection,
8 | IconTerminal2
9 | } from "@tabler/icons-react";
10 | import Image from "next/image";
11 | import { FlipWords } from "@/components/ui/flip-words";
12 | import { SparklesCore } from "@/components/ui/sparkles";
13 |
14 | export default function HomeScreen() {
15 | const words = ["Hi! I'm Priyanka Sharma"];
16 | return (
17 |
18 | {/* home screen */}
19 |
20 |
21 |
22 |
27 |
28 |
29 |
30 | A Software Developer {" "}
31 | specializing in frontend and{" "}
32 | mobile app development.
33 |
34 |
35 | I thrive on challenges, passionate about{" "}
36 | learning new skills ,{/*
*/}
37 | {/*
*/} and{" "}
38 | dedicated to writing clean ,{" "}
39 | professional code .
40 |
41 |
42 |
43 |
44 | {/* Gradients */}
45 |
46 |
47 |
48 |
49 |
50 | {/* Core component */}
51 |
59 |
60 | {/* Radial Gradient to prevent sharp edges */}
61 |
62 |
63 |
64 |
65 | );
66 | }
67 |
68 | const links = [
69 | {
70 | title: "Home",
71 | icon: (
72 |
73 | ),
74 | href: "#"
75 | },
76 |
77 | {
78 | title: "Products",
79 | icon: (
80 |
81 | ),
82 | href: "#"
83 | },
84 | {
85 | title: "Components",
86 | icon: (
87 |
88 | ),
89 | href: "#"
90 | },
91 | {
92 | title: "Aceternity UI",
93 | icon: (
94 |
100 | ),
101 | href: "#"
102 | },
103 | {
104 | title: "Changelog",
105 | icon: (
106 |
107 | ),
108 | href: "#"
109 | },
110 |
111 | {
112 | title: "Twitter",
113 | icon: (
114 |
115 | ),
116 | href: "#"
117 | },
118 | {
119 | title: "GitHub",
120 | icon: (
121 |
122 | ),
123 | href: "#"
124 | }
125 | ];
126 |
--------------------------------------------------------------------------------
/src/app/pages/networking.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import React from "react";
4 | import { FlipWords } from "@/components/ui/flip-words";
5 | import { ParallaxScroll } from "@/components/ui/parallax-scroll";
6 |
7 | const Networking = () => {
8 | const words = ["Connecting, Learning, and Growing Together"];
9 |
10 | return (
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | Explore my insights and experiences from various{" "}
20 | industry events and{" "}
21 | meetups , where I share{" "}
22 | key takeaways ,{" "}
23 | valuable connections , and moments
24 | that shaped my professional journey.
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | );
35 | };
36 |
37 | export default Networking;
38 |
39 | const images = [
40 | {
41 | src: "/networking-1.png",
42 | href: "https://www.linkedin.com/feed/update/urn:li:activity:7306864289519128576"
43 | },
44 | {
45 | src: "/networking-2.png",
46 | href: "https://www.linkedin.com/posts/priyanka-s-b79401142_keploy-gittogether-opensourcecommunity-activity-7169236453577646080-YoXh?utm_source=share&utm_medium=member_desktop"
47 | },
48 | {
49 | src: "/networking-3.png",
50 | href: "https://www.linkedin.com/posts/priyanka-s-b79401142_serverlessdays-bangalore-techcommunity-activity-7235735531211345920-RoQg?utm_source=share&utm_medium=member_desktop"
51 | },
52 | {
53 | src: "/networking-4.png",
54 | href: "https://www.linkedin.com/posts/technexuscommunity_microsoftai-azureopenai-aiinnovation-activity-7302707221094666241-9zWP?utm_source=share&utm_medium=member_desktop&rcm=ACoAACKWXU0BijJEUI16M7ei08EhKNgho2RX3xM"
55 | },
56 | {
57 | src: "/networking-5.png",
58 | href: "https://www.linkedin.com/posts/priyanka-s-b79401142_thats-a-wrap-for-serverlessdays-bengaluru-activity-7235948907954892802-3tpT?utm_source=share&utm_medium=member_desktop"
59 | },
60 | {
61 | src: "/networking-6.png",
62 | href: "https://www.linkedin.com/posts/priyanka-s-b79401142_githubconstellation-oss-developercommunity-activity-7206725289031196673-8D-l?utm_source=share&utm_medium=member_desktop"
63 | },
64 | {
65 | src: "/networking-7.png",
66 | href: "https://x.com/lassiecoder/status/1836049315778678872"
67 | },
68 | {
69 | src: "/networking-8.png",
70 | href: "https://x.com/lassiecoder/status/1829883911675183349"
71 | },
72 | {
73 | src: "/networking-9.png",
74 | href: "https://www.linkedin.com/posts/priyanka-s-b79401142_gittogether-gittogetherbengaluru-opensource-activity-7233815879728123904-XVV9?utm_source=share&utm_medium=member_desktop"
75 | },
76 | {
77 | src: "/networking-10.png",
78 | href: "https://x.com/adityaoberai1/status/1763221813625331791"
79 | },
80 | {
81 | src: "/networking-11.png",
82 | href: "https://www.linkedin.com/posts/priyanka-s-b79401142_elevatevirtualconference-girlgeekx-networking-activity-7204481662913544193-aFAM?utm_source=share&utm_medium=member_desktop"
83 | },
84 | {
85 | src: "/networking-12.png",
86 | href: "https://x.com/edjgeek/status/1830168978603282712"
87 | },
88 | {
89 | src: "/networking-13.png",
90 | href: "https://x.com/lassiecoder/status/1823067516165308606"
91 | },
92 | {
93 | src: "/networking-14.png",
94 | href: "https://www.linkedin.com/posts/priyanka-s-b79401142_gittogether-opensource-techcommunity-activity-7215039647247159296-g6qD?utm_source=share&utm_medium=member_desktop"
95 | }
96 | ];
97 |
--------------------------------------------------------------------------------
/src/app/pages/projects.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import React, { useEffect, useState } from "react";
4 | import Link from "next/link";
5 | import Image from "next/image";
6 | import { FaStar } from "react-icons/fa6";
7 | import { PiGitForkBold } from "react-icons/pi";
8 | import { ButtonsCard } from "@/components/ui/tailwindcss-buttons";
9 | import { CardBody, CardContainer, CardItem } from "@/components/ui/3d-card.tsx";
10 |
11 | const GITHUB_USERNAME = "lassiecoder";
12 |
13 | const ThreeDCard = () => {
14 | const [repoStats, setRepoStats] = useState<{
15 | [key: string]: { stars: number; forks: number };
16 | }>({});
17 |
18 | useEffect(() => {
19 | const fetchRepoStats = async () => {
20 | try {
21 | const repoData = await Promise.all(
22 | dummyData.map(async (item) => {
23 | const response = await fetch(
24 | `https://api.github.com/repos/${GITHUB_USERNAME}/${item.repo}`
25 | );
26 | const data = await response.json();
27 | return {
28 | repo: item.repo,
29 | stars: data.stargazers_count,
30 | forks: data.forks_count
31 | };
32 | })
33 | );
34 |
35 | const stats = repoData.reduce(
36 | (acc: { [key: string]: { stars: number; forks: number } }, curr) => {
37 | acc[curr.repo] = { stars: curr.stars, forks: curr.forks };
38 | return acc;
39 | },
40 | {}
41 | );
42 |
43 | setRepoStats(stats);
44 | } catch (error) {
45 | console.error("Failed to fetch GitHub data", error);
46 | }
47 | };
48 |
49 | fetchRepoStats();
50 | }, []);
51 |
52 | return (
53 |
54 |
55 |
56 | Projects
57 |
58 |
59 |
60 | {dummyData.map((item, index) => (
61 |
62 |
63 |
64 | {/* Title */}
65 |
69 | {item.title}
70 |
71 |
72 | {/* Description with Clamp */}
73 |
78 | {item.description}
79 |
80 |
81 | {/* Image with Fixed Height */}
82 |
83 |
91 |
92 |
93 | {/* Stats and Button */}
94 |
95 | {item.projectType !== "work-project" && (
96 |
97 | {repoStats[item.repo]?.stars !== 0 && (
98 |
99 |
100 | {repoStats[item.repo]?.stars || 0}
101 |
102 | )}
103 |
104 | {repoStats[item.repo]?.forks !== 0 && (
105 |
106 |
107 | {repoStats[item.repo]?.forks || 0}
108 |
109 | )}
110 |
111 | )}
112 |
113 |
114 |
115 |
116 |
117 |
118 | View Project →
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 | ))}
128 |
129 |
130 | );
131 | };
132 |
133 | export default ThreeDCard;
134 |
135 | const dummyData = [
136 | {
137 | title: "Community Health Files",
138 | description:
139 | "The community-health-files package automates the setup and management for open-source projects, providing a streamlined way to maintain project guidelines and policies.",
140 | image: "/project-1.png",
141 | link: "https://github.com/lassiecoder/community-health-files",
142 | repo: "community-health-files",
143 | projectType: ""
144 | },
145 | {
146 | title: "GitHub README",
147 | description:
148 | "A dynamic GitHub profile showcasing JavaScript expertise, tech writing, speaking, and community contributions with engaging visuals, stats, and social links.",
149 | image: "/project-2.png",
150 | link: "https://github.com/lassiecoder/lassiecoder",
151 | repo: "lassiecoder",
152 | projectType: ""
153 | },
154 | {
155 | title: "Shoplane – E-commerce website",
156 | description:
157 | "Shoplane's GitHub repository, with 340 stars and 250 forks, is a significant player in open-source e-commerce, influencing the online retail sector's development.",
158 | image: "/project-3.png",
159 | link: "https://github.com/lassiecoder/E-CommerceWebsite",
160 | repo: "E-CommerceWebsite",
161 | projectType: ""
162 | },
163 | {
164 | title: "npx lassiecoder – in your terminal?",
165 | description:
166 | "A personalized command-line business card. This innovative tool allows you to showcase your professional profile, skills, and contact information in the terminal.",
167 | image: "/project-4.gif",
168 | link: "https://github.com/lassiecoder/npx-lassiecoder",
169 | repo: "npx-lassiecoder",
170 | projectType: ""
171 | },
172 | {
173 | title: "EduFund - Mutual Funds & SIP",
174 | description:
175 | "EduFund, India's leading investment app, helps parents save for their children's education, ensuring a brighter future amid rising education expenses.",
176 | image: "/project-5.png",
177 | link: "https://play.google.com/store/apps/details?id=com.educationfund.edufund",
178 | repo: "",
179 | projectType: "work-project"
180 | },
181 | {
182 | title: "Torum: Cryptocurrency Social App",
183 | description:
184 | "Torum's mobile app fosters a vibrant SocialFi ecosystem, connecting over 230,000 cryptocurrency enthusiasts since its 2018 inception.",
185 | image: "/project-6.png",
186 | link: "https://play.google.com/store/apps/details?id=com.torum.app&hl=en_IN&gl=US",
187 | repo: "",
188 | projectType: "work-project"
189 | },
190 | {
191 | title: "Mutual funding app",
192 | description:
193 | "The proof-of-concept app exhibits mutual funds with authentication, presenting a scrollable list of key fund information. Selecting a fund directs users to a detailed product page for additional insights.",
194 | image: "/project-7.png",
195 | link: "https://github.com/lassiecoder/mutual-funding-app",
196 | repo: "mutual-funding-app",
197 | projectType: ""
198 | },
199 | {
200 | title: "Adecco",
201 | description:
202 | "The Adecco mobile app transforms job placement with accuracy, speed, and thorough evaluation. Daily linking over 700,000 individuals to top-tier global opportunities.",
203 | image: "/project-8.png",
204 | link: "https://play.google.com/store/apps/details?id=com.adecco.app20&hl=en_IN&gl=US",
205 | repo: "",
206 | projectType: "work-project"
207 | }
208 | ];
209 |
--------------------------------------------------------------------------------
/src/components/Tooltip.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import React from "react";
4 |
5 | interface TooltipProps {
6 | text: string; // The text to display
7 | tooltipText: string; // The content of the tooltip
8 | className?: string; // Optional className for styling the text
9 | }
10 |
11 | const Tooltip: React.FC
= ({ text, tooltipText, className }) => {
12 | return (
13 |
14 | {text}
15 |
16 | {tooltipText}
17 |
18 |
19 | );
20 | };
21 |
22 | export default Tooltip;
23 |
--------------------------------------------------------------------------------
/src/components/footer.tsx:
--------------------------------------------------------------------------------
1 | import ReactGA from "react-ga4";
2 | import Image from "next/image";
3 | import { FaSquareXTwitter } from "react-icons/fa6";
4 | import { IoNewspaperOutline } from "react-icons/io5";
5 |
6 | import {
7 | FaGithub,
8 | FaLinkedinIn,
9 | FaInstagram,
10 | FaMailBulk
11 | } from "react-icons/fa";
12 | import Link from "next/link";
13 |
14 | export default function Footer() {
15 | const trackSponsorClick = () => {
16 | ReactGA.event("sponsorship_click_header", {
17 | category: "Sponsorship",
18 | label: "GitHub Sponsor Button"
19 | });
20 | };
21 |
22 | return (
23 |
24 | {/* Container that changes between centered/between based on screen size */}
25 |
26 | {/* Left Side - GitHub Sponsor Button */}
27 |
32 |
40 |
41 |
42 | {/* Social Icons - Centered on small screens */}
43 |
44 |
49 |
54 |
59 |
64 |
69 |
74 |
75 |
76 |
77 | );
78 | }
79 |
80 | interface SocialLinkProps {
81 | href: string;
82 | icon: React.ComponentType<{ className?: string }>;
83 | label: string;
84 | }
85 |
86 | const SocialLink: React.FC = ({ href, icon: Icon, label }) => {
87 | return (
88 |
89 |
90 |
91 |
92 | {label}
93 |
94 |
95 |
96 | );
97 | };
98 |
--------------------------------------------------------------------------------
/src/components/ui/3d-card.tsx.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import React, {
4 | createContext,
5 | useState,
6 | useContext,
7 | useRef,
8 | useEffect,
9 | } from "react";
10 | import { cn } from "../utils/cn";
11 |
12 | const MouseEnterContext = createContext<
13 | [boolean, React.Dispatch>] | undefined
14 | >(undefined);
15 |
16 | export const CardContainer = ({
17 | children,
18 | className,
19 | containerClassName,
20 | }: {
21 | children?: React.ReactNode;
22 | className?: string;
23 | containerClassName?: string;
24 | }) => {
25 | const containerRef = useRef(null);
26 | const [isMouseEntered, setIsMouseEntered] = useState(false);
27 |
28 | const handleMouseMove = (e: React.MouseEvent) => {
29 | if (!containerRef.current) return;
30 | const { left, top, width, height } =
31 | containerRef.current.getBoundingClientRect();
32 | const x = (e.clientX - left - width / 2) / 25;
33 | const y = (e.clientY - top - height / 2) / 25;
34 | containerRef.current.style.transform = `rotateY(${x}deg) rotateX(${y}deg)`;
35 | };
36 |
37 | const handleMouseEnter = (e: React.MouseEvent) => {
38 | setIsMouseEntered(true);
39 | if (!containerRef.current) return;
40 | };
41 |
42 | const handleMouseLeave = (e: React.MouseEvent) => {
43 | if (!containerRef.current) return;
44 | setIsMouseEntered(false);
45 | containerRef.current.style.transform = `rotateY(0deg) rotateX(0deg)`;
46 | };
47 | return (
48 |
49 |
58 |
71 | {children}
72 |
73 |
74 |
75 | );
76 | };
77 |
78 | export const CardBody = ({
79 | children,
80 | className,
81 | }: {
82 | children: React.ReactNode;
83 | className?: string;
84 | }) => {
85 | return (
86 | *]:[transform-style:preserve-3d]",
89 | className
90 | )}
91 | >
92 | {children}
93 |
94 | );
95 | };
96 |
97 | export const CardItem = ({
98 | as: Tag = "div",
99 | children,
100 | className,
101 | translateX = 0,
102 | translateY = 0,
103 | translateZ = 0,
104 | rotateX = 0,
105 | rotateY = 0,
106 | rotateZ = 0,
107 | ...rest
108 | }: {
109 | as?: React.ElementType;
110 | children: React.ReactNode;
111 | className?: string;
112 | translateX?: number | string;
113 | translateY?: number | string;
114 | translateZ?: number | string;
115 | rotateX?: number | string;
116 | rotateY?: number | string;
117 | rotateZ?: number | string;
118 | [key: string]: any;
119 | }) => {
120 | const ref = useRef(null);
121 | const [isMouseEntered] = useMouseEnter();
122 |
123 | useEffect(() => {
124 | handleAnimations();
125 | }, [isMouseEntered]);
126 |
127 | const handleAnimations = () => {
128 | if (!ref.current) return;
129 | if (isMouseEntered) {
130 | ref.current.style.transform = `translateX(${translateX}px) translateY(${translateY}px) translateZ(${translateZ}px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) rotateZ(${rotateZ}deg)`;
131 | } else {
132 | ref.current.style.transform = `translateX(0px) translateY(0px) translateZ(0px) rotateX(0deg) rotateY(0deg) rotateZ(0deg)`;
133 | }
134 | };
135 |
136 | return (
137 |
142 | {children}
143 |
144 | );
145 | };
146 |
147 | // Create a hook to use the context
148 | export const useMouseEnter = () => {
149 | const context = useContext(MouseEnterContext);
150 | if (context === undefined) {
151 | throw new Error("useMouseEnter must be used within a MouseEnterProvider");
152 | }
153 | return context;
154 | };
155 |
--------------------------------------------------------------------------------
/src/components/ui/3d-pin.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import React, { useState } from "react";
3 | import { motion } from "framer-motion";
4 | import { cn } from "../utils/cn";
5 |
6 | export const PinContainer = ({
7 | children,
8 | title,
9 | href,
10 | className,
11 | containerClassName
12 | }: {
13 | children: React.ReactNode;
14 | title?: string;
15 | href?: string;
16 | className?: string;
17 | containerClassName?: string;
18 | }) => {
19 | const [transform, setTransform] = useState(
20 | "translate(-50%,-50%) rotateX(0deg)"
21 | );
22 |
23 | const onMouseEnter = () => {
24 | setTransform("translate(-50%,-50%) rotateX(40deg) scale(0.8)");
25 | };
26 | const onMouseLeave = () => {
27 | setTransform("translate(-50%,-50%) rotateX(0deg) scale(1)");
28 | };
29 |
30 | return (
31 |
57 | );
58 | };
59 |
60 | export const PinPerspective = ({
61 | title,
62 | href
63 | }: {
64 | title?: string;
65 | href?: string;
66 | }) => {
67 | return (
68 | //
69 |
75 |
76 |
89 |
90 |
97 | <>
98 |
121 |
144 |
167 | >
168 |
169 |
170 | <>
171 |
177 |
183 |
189 |
195 | >
196 |
197 |
198 | );
199 | };
200 |
--------------------------------------------------------------------------------
/src/components/ui/flip-words.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import React, { useCallback, useEffect, useRef, useState } from "react";
3 | import { AnimatePresence, motion, LayoutGroup } from "framer-motion";
4 | import { cn } from "../utils/cn";
5 |
6 | export const FlipWords = ({
7 | words,
8 | duration = 1000,
9 | className
10 | }: {
11 | words: string[];
12 | duration?: number;
13 | className?: string;
14 | }) => {
15 | const [currentWord, setCurrentWord] = useState(words[0]);
16 | const [isAnimating, setIsAnimating] = useState(false);
17 |
18 | const startAnimation = useCallback(() => {
19 | const word = words[words.indexOf(currentWord) + 1] || words[0];
20 | setCurrentWord(word);
21 | setIsAnimating(true);
22 | }, [currentWord, words]);
23 |
24 | useEffect(() => {
25 | if (!isAnimating)
26 | setTimeout(() => {
27 | startAnimation();
28 | }, duration);
29 | }, [isAnimating, duration, startAnimation]);
30 |
31 | return (
32 | {
34 | setIsAnimating(false);
35 | }}
36 | >
37 |
67 | {currentWord.split(" ").map((word, wordIndex) => (
68 |
78 | {word.split("").map((letter, letterIndex) => (
79 |
89 | {letter}
90 |
91 | ))}
92 |
93 |
94 | ))}
95 |
96 |
97 | );
98 | };
99 |
--------------------------------------------------------------------------------
/src/components/ui/floating-dock.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * Note: Use position fixed according to your needs
3 | * Desktop navbar is better positioned at the bottom
4 | * Mobile navbar is better positioned at bottom right.
5 | **/
6 |
7 | import { cn } from "../utils/cn";
8 | import { IconLayoutNavbarCollapse } from "@tabler/icons-react";
9 | import {
10 | AnimatePresence,
11 | MotionValue,
12 | motion,
13 | useMotionValue,
14 | useSpring,
15 | useTransform
16 | } from "framer-motion";
17 | import Link from "next/link";
18 | import { useRef, useState } from "react";
19 |
20 | export const FloatingDock = ({
21 | items,
22 | desktopClassName,
23 | mobileClassName
24 | }: {
25 | items: { title: string; icon: React.ReactNode; href: string }[];
26 | desktopClassName?: string;
27 | mobileClassName?: string;
28 | }) => {
29 | return (
30 | <>
31 |
32 |
33 | >
34 | );
35 | };
36 |
37 | const FloatingDockMobile = ({
38 | items,
39 | className
40 | }: {
41 | items: { title: string; icon: React.ReactNode; href: string }[];
42 | className?: string;
43 | }) => {
44 | const [open, setOpen] = useState(false);
45 | return (
46 |
47 |
48 | {open && (
49 |
56 | {items.map((item, idx) => (
57 |
73 |
78 | {item.icon}
79 |
80 |
81 | ))}
82 |
83 | )}
84 |
85 |
setOpen(!open)}
87 | className="h-10 w-10 rounded-full bg-gray-50 dark:bg-neutral-800 flex items-center justify-center"
88 | >
89 |
90 |
91 |
92 | );
93 | };
94 |
95 | const FloatingDockDesktop = ({
96 | items,
97 | className
98 | }: {
99 | items: { title: string; icon: React.ReactNode; href: string }[];
100 | className?: string;
101 | }) => {
102 | let mouseX = useMotionValue(Infinity);
103 | return (
104 | mouseX.set(e.pageX)}
106 | // onMouseLeave={() => mouseX.set(Infinity)}
107 | {...{
108 | onMouseMove: (e: MouseEvent) => mouseX.set(e.pageX),
109 | onMouseLeave: (e: MouseEvent) => mouseX.set(Infinity),
110 | className: cn(
111 | "mx-auto hidden md:flex h-16 gap-4 items-end rounded-2xl bg-gray-50 dark:bg-neutral-900 px-4 pb-3",
112 | className
113 | )
114 | }}
115 | >
116 | {items.map((item) => (
117 |
118 | ))}
119 |
120 | );
121 | };
122 |
123 | function IconContainer({
124 | mouseX,
125 | title,
126 | icon,
127 | href
128 | }: {
129 | mouseX: MotionValue;
130 | title: string;
131 | icon: React.ReactNode;
132 | href: string;
133 | }) {
134 | let ref = useRef(null);
135 |
136 | let distance = useTransform(mouseX, (val) => {
137 | let bounds = ref.current?.getBoundingClientRect() ?? { x: 0, width: 0 };
138 |
139 | return val - bounds.x - bounds.width / 2;
140 | });
141 |
142 | let widthTransform = useTransform(distance, [-100, 0, 100], [40, 80, 40]);
143 | let heightTransform = useTransform(distance, [-100, 0, 100], [40, 80, 40]);
144 |
145 | let widthTransformIcon = useTransform(distance, [-100, 0, 100], [20, 40, 20]);
146 | let heightTransformIcon = useTransform(
147 | distance,
148 | [-100, 0, 100],
149 | [20, 40, 20]
150 | );
151 |
152 | let width = useSpring(widthTransform, {
153 | mass: 0.1,
154 | stiffness: 150,
155 | damping: 12
156 | });
157 | let height = useSpring(heightTransform, {
158 | mass: 0.1,
159 | stiffness: 150,
160 | damping: 12
161 | });
162 |
163 | let widthIcon = useSpring(widthTransformIcon, {
164 | mass: 0.1,
165 | stiffness: 150,
166 | damping: 12
167 | });
168 | let heightIcon = useSpring(heightTransformIcon, {
169 | mass: 0.1,
170 | stiffness: 150,
171 | damping: 12
172 | });
173 |
174 | const [hovered, setHovered] = useState(false);
175 |
176 | return (
177 |
178 | setHovered(true),
183 | onMouseLeave: () => setHovered(false),
184 | className:
185 | "aspect-square rounded-full bg-gray-200 dark:bg-neutral-800 flex items-center justify-center relative"
186 | }}
187 | >
188 |
189 | {/* {hovered && (
190 |
196 | {title}
197 |
198 | )} */}
199 |
200 |
204 | {icon}
205 |
206 |
207 |
208 | );
209 | }
210 |
--------------------------------------------------------------------------------
/src/components/ui/parallax-scroll.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { useRef } from "react";
4 | import Link from "next/link";
5 | import Image from "next/image";
6 | import { cn } from "../utils/cn";
7 | import { motion } from "framer-motion";
8 | import { useScroll, useTransform } from "framer-motion";
9 |
10 | export const ParallaxScroll = ({
11 | items,
12 | className
13 | }: {
14 | items: { src: string; href: string }[];
15 | className?: string;
16 | }) => {
17 | const gridRef = useRef(null);
18 | const { scrollYProgress } = useScroll({
19 | container: gridRef,
20 | offset: ["start start", "end start"]
21 | });
22 |
23 | const translateFirst = useTransform(scrollYProgress, [0, 1], [0, -200]);
24 | const translateSecond = useTransform(scrollYProgress, [0, 1], [0, 200]);
25 | const translateThird = useTransform(scrollYProgress, [0, 1], [0, -200]);
26 | const translateFourth = useTransform(scrollYProgress, [0, 1], [0, 200]);
27 | const translateFifth = useTransform(scrollYProgress, [0, 1], [0, -200]);
28 |
29 | // Adjust the division to create 5 parts instead of 4
30 | const fifth = Math.ceil(items.length / 5);
31 |
32 | const firstPart = items.slice(0, fifth);
33 | const secondPart = items.slice(fifth, 2 * fifth);
34 | const thirdPart = items.slice(2 * fifth, 3 * fifth);
35 | const fourthPart = items.slice(3 * fifth, 4 * fifth);
36 | const fifthPart = items.slice(4 * fifth);
37 |
38 | return (
39 |
46 |
47 |
48 | {firstPart.map(({ src, href }, idx) => (
49 |
50 |
51 |
60 |
61 |
62 | ))}
63 |
64 |
65 | {secondPart.map(({ src, href }, idx) => (
66 |
67 |
68 |
77 |
78 |
79 | ))}
80 |
81 |
82 | {thirdPart.map(({ src, href }, idx) => (
83 |
84 |
85 |
94 |
95 |
96 | ))}
97 |
98 |
99 | {fourthPart.map(({ src, href }, idx) => (
100 |
101 |
102 |
111 |
112 |
113 | ))}
114 |
115 |
116 | {fifthPart.map(({ src, href }, idx) => (
117 |
118 |
119 |
128 |
129 |
130 | ))}
131 |
132 |
133 |
134 | );
135 | };
136 |
--------------------------------------------------------------------------------
/src/components/ui/sparkles.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import React from "react";
3 | import { useEffect, useState } from "react";
4 | import Particles, { initParticlesEngine } from "@tsparticles/react";
5 | import type { Container, SingleOrMultiple } from "@tsparticles/engine";
6 | import { loadSlim } from "@tsparticles/slim";
7 | import { cn } from "../utils/cn";
8 | import { motion, useAnimation } from "framer-motion";
9 |
10 | type ParticlesProps = {
11 | id?: string;
12 | className?: string;
13 | background?: string;
14 | particleSize?: number;
15 | minSize?: number;
16 | maxSize?: number;
17 | speed?: number;
18 | particleColor?: string;
19 | particleDensity?: number;
20 | };
21 | export const SparklesCore = (props: ParticlesProps) => {
22 | const {
23 | id,
24 | className,
25 | background,
26 | minSize,
27 | maxSize,
28 | speed,
29 | particleColor,
30 | particleDensity
31 | } = props;
32 | const [init, setInit] = useState(false);
33 | useEffect(() => {
34 | initParticlesEngine(async (engine) => {
35 | await loadSlim(engine);
36 | }).then(() => {
37 | setInit(true);
38 | });
39 | }, []);
40 | const controls = useAnimation();
41 |
42 | const particlesLoaded = async (container?: Container) => {
43 | if (container) {
44 | console.log(container);
45 | controls.start({
46 | opacity: 1,
47 | transition: {
48 | duration: 1
49 | }
50 | });
51 | }
52 | };
53 |
54 | return (
55 |
59 | {init && (
60 | | undefined
164 | },
165 | groups: {},
166 | move: {
167 | angle: {
168 | offset: 0,
169 | value: 90
170 | },
171 | attract: {
172 | distance: 200,
173 | enable: false,
174 | rotate: {
175 | x: 3000,
176 | y: 3000
177 | }
178 | },
179 | center: {
180 | x: 50,
181 | y: 50,
182 | mode: "percent",
183 | radius: 0
184 | },
185 | decay: 0,
186 | distance: {},
187 | direction: "none",
188 | drift: 0,
189 | enable: true,
190 | gravity: {
191 | acceleration: 9.81,
192 | enable: false,
193 | inverse: false,
194 | maxSpeed: 50
195 | },
196 | path: {
197 | clamp: true,
198 | delay: {
199 | value: 0
200 | },
201 | enable: false,
202 | options: {}
203 | },
204 | outModes: {
205 | default: "out"
206 | },
207 | random: false,
208 | size: false,
209 | speed: {
210 | min: 0.1,
211 | max: 1
212 | },
213 | spin: {
214 | acceleration: 0,
215 | enable: false
216 | },
217 | straight: false,
218 | trail: {
219 | enable: false,
220 | length: 10,
221 | fill: {}
222 | },
223 | vibrate: false,
224 | warp: false
225 | },
226 | number: {
227 | density: {
228 | enable: true,
229 | width: 400,
230 | height: 400
231 | },
232 | limit: {
233 | mode: "delete",
234 | value: 0
235 | },
236 | value: particleDensity || 120
237 | },
238 | opacity: {
239 | value: {
240 | min: 0.1,
241 | max: 1
242 | },
243 | animation: {
244 | count: 0,
245 | enable: true,
246 | speed: speed || 4,
247 | decay: 0,
248 | delay: 0,
249 | sync: false,
250 | mode: "auto",
251 | startValue: "random",
252 | destroy: "none"
253 | }
254 | },
255 | reduceDuplicates: false,
256 | shadow: {
257 | blur: 0,
258 | color: {
259 | value: "#000"
260 | },
261 | enable: false,
262 | offset: {
263 | x: 0,
264 | y: 0
265 | }
266 | },
267 | shape: {
268 | close: true,
269 | fill: true,
270 | options: {},
271 | type: "circle"
272 | },
273 | size: {
274 | value: {
275 | min: minSize || 1,
276 | max: maxSize || 3
277 | },
278 | animation: {
279 | count: 0,
280 | enable: false,
281 | speed: 5,
282 | decay: 0,
283 | delay: 0,
284 | sync: false,
285 | mode: "auto",
286 | startValue: "random",
287 | destroy: "none"
288 | }
289 | },
290 | stroke: {
291 | width: 0
292 | },
293 | zIndex: {
294 | value: 0,
295 | opacityRate: 1,
296 | sizeRate: 1,
297 | velocityRate: 1
298 | },
299 | destroy: {
300 | bounds: {},
301 | mode: "none",
302 | split: {
303 | count: 1,
304 | factor: {
305 | value: 3
306 | },
307 | rate: {
308 | value: {
309 | min: 4,
310 | max: 9
311 | }
312 | },
313 | sizeOffset: true
314 | }
315 | },
316 | roll: {
317 | darken: {
318 | enable: false,
319 | value: 0
320 | },
321 | enable: false,
322 | enlighten: {
323 | enable: false,
324 | value: 0
325 | },
326 | mode: "vertical",
327 | speed: 25
328 | },
329 | tilt: {
330 | value: 0,
331 | animation: {
332 | enable: false,
333 | speed: 0,
334 | decay: 0,
335 | sync: false
336 | },
337 | direction: "clockwise",
338 | enable: false
339 | },
340 | twinkle: {
341 | lines: {
342 | enable: false,
343 | frequency: 0.05,
344 | opacity: 1
345 | },
346 | particles: {
347 | enable: false,
348 | frequency: 0.05,
349 | opacity: 1
350 | }
351 | },
352 | wobble: {
353 | distance: 5,
354 | enable: false,
355 | speed: {
356 | angle: 50,
357 | move: 10
358 | }
359 | },
360 | life: {
361 | count: 0,
362 | delay: {
363 | value: 0,
364 | sync: false
365 | },
366 | duration: {
367 | value: 0,
368 | sync: false
369 | }
370 | },
371 | rotate: {
372 | value: 0,
373 | animation: {
374 | enable: false,
375 | speed: 0,
376 | decay: 0,
377 | sync: false
378 | },
379 | direction: "clockwise",
380 | path: false
381 | },
382 | orbit: {
383 | animation: {
384 | count: 0,
385 | enable: false,
386 | speed: 1,
387 | decay: 0,
388 | delay: 0,
389 | sync: false
390 | },
391 | enable: false,
392 | opacity: 1,
393 | rotation: {
394 | value: 45
395 | },
396 | width: 1
397 | },
398 | links: {
399 | blink: false,
400 | color: {
401 | value: "#fff"
402 | },
403 | consent: false,
404 | distance: 100,
405 | enable: false,
406 | frequency: 1,
407 | opacity: 1,
408 | shadow: {
409 | blur: 5,
410 | color: {
411 | value: "#000"
412 | },
413 | enable: false
414 | },
415 | triangles: {
416 | enable: false,
417 | frequency: 1
418 | },
419 | width: 1,
420 | warp: false
421 | },
422 | repulse: {
423 | value: 0,
424 | enabled: false,
425 | distance: 1,
426 | duration: 1,
427 | factor: 1,
428 | speed: 1
429 | }
430 | },
431 | detectRetina: true
432 | }}
433 | />
434 | )}
435 |
436 | );
437 | };
438 |
--------------------------------------------------------------------------------
/src/components/ui/tailwindcss-buttons.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import React from "react";
3 | import { IconClipboard } from "@tabler/icons-react";
4 | import { cn } from "../utils/cn";
5 |
6 | export const ButtonsCard = ({
7 | children,
8 | className,
9 | onClick,
10 | }: {
11 | children?: React.ReactNode;
12 | className?: string;
13 | onClick?: () => void;
14 | }) => {
15 | return (
16 |
17 |
18 |
19 |
{children}
20 |
21 | );
22 | };
23 |
--------------------------------------------------------------------------------
/src/components/ui/timeline.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import {
3 | useMotionValueEvent,
4 | useScroll,
5 | useTransform,
6 | motion
7 | } from "framer-motion";
8 | import React, { useEffect, useRef, useState } from "react";
9 |
10 | interface TimelineEntry {
11 | title: React.ReactNode;
12 | content: React.ReactNode;
13 | smallScreenLogo: React.ReactNode;
14 | }
15 |
16 | export const Timeline = ({ data }: { data: TimelineEntry[] }) => {
17 | const ref = useRef(null);
18 | // const containerRef = useRef(null);
19 | // const containerRef = useRef(
20 | // null!
21 | // ) as React.RefObject;
22 | const containerRef = useRef(null);
23 |
24 | const [height, setHeight] = useState(0);
25 | const [isSmallScreen, setIsSmallScreen] = useState(false);
26 |
27 | useEffect(() => {
28 | const handleResize = () => {
29 | setIsSmallScreen(window.innerWidth <= 470);
30 | };
31 |
32 | handleResize();
33 | window.addEventListener("resize", handleResize);
34 |
35 | return () => window.removeEventListener("resize", handleResize);
36 | }, []);
37 |
38 | useEffect(() => {
39 | if (ref.current) {
40 | const rect = ref.current.getBoundingClientRect();
41 | setHeight(rect.height);
42 | }
43 | }, [ref]);
44 |
45 | // const { scrollYProgress } = useScroll({
46 | // target: containerRef,
47 | // offset: ["start 10%", "end 50%"]
48 | // });
49 | const { scrollYProgress } = useScroll({
50 | target: containerRef as React.RefObject, // Ensure compatibility
51 | offset: ["start 10%", "end 50%"]
52 | });
53 |
54 | const heightTransform = useTransform(scrollYProgress, [0, 1], [0, height]);
55 | const opacityTransform = useTransform(scrollYProgress, [0, 0.1], [0, 1]);
56 |
57 | return (
58 |
59 |
60 | <>
61 | {isSmallScreen
62 | ? // Render SMALL SCREEN layout
63 | data.map((item, index) => (
64 |
65 | {/* Sticky section with 20% width */}
66 |
67 |
68 |
{item.smallScreenLogo}
69 |
70 |
71 |
72 | {/* Content section with 80% width */}
73 |
74 | {!isSmallScreen && (
75 |
76 | {item.title}
77 |
78 | )}
79 |
80 | {item.content}
81 |
82 |
83 | ))
84 | : // Render LARGE SCREEN layout
85 | data.map((item, index) => (
86 |
87 |
88 |
91 |
92 |
93 | {item.title}
94 |
95 |
96 |
97 |
98 |
99 |
100 | {item.title}
101 |
102 | {item.content}
103 |
104 |
105 | ))}
106 | >
107 | {!isSmallScreen && (
108 |
114 |
124 |
125 | )}
126 |
127 |
128 | );
129 | };
130 |
--------------------------------------------------------------------------------
/src/components/ui/tracing-beam.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 | import React, { useEffect, useRef, useState } from "react";
3 | import {
4 | motion,
5 | useTransform,
6 | useScroll,
7 | useVelocity,
8 | useSpring
9 | } from "framer-motion";
10 | import { cn } from "../utils/cn";
11 |
12 | export const TracingBeam = ({
13 | children,
14 | className
15 | }: {
16 | children: React.ReactNode;
17 | className?: string;
18 | }) => {
19 | // const ref = useRef(null);
20 | const ref = useRef(null!) as React.RefObject;
21 | const { scrollYProgress } = useScroll({
22 | target: ref,
23 | offset: ["start start", "end start"]
24 | });
25 |
26 | const contentRef = useRef(null);
27 | const [svgHeight, setSvgHeight] = useState(0);
28 |
29 | useEffect(() => {
30 | if (contentRef.current) {
31 | setSvgHeight(contentRef.current.offsetHeight);
32 | }
33 | }, []);
34 |
35 | const y1 = useSpring(
36 | useTransform(scrollYProgress, [0, 0.8], [50, svgHeight]),
37 | {
38 | stiffness: 500,
39 | damping: 90
40 | }
41 | );
42 | const y2 = useSpring(
43 | useTransform(scrollYProgress, [0, 1], [50, svgHeight - 200]),
44 | {
45 | stiffness: 500,
46 | damping: 90
47 | }
48 | );
49 |
50 | return (
51 |
57 |
58 | 0
66 | ? "none"
67 | : "rgba(0, 0, 0, 0.24) 0px 3px 8px"
68 | }}
69 | {...{
70 | className:
71 | "ml-[27px] h-4 w-4 rounded-full border border-netural-200 shadow-sm flex items-center justify-center"
72 | }}
73 | >
74 | 0 ? "white" : "var(--emerald-500)",
82 | borderColor:
83 | scrollYProgress.get() > 0 ? "white" : "var(--emerald-600)"
84 | }}
85 | {...{
86 | className:
87 | "h-2 w-2 rounded-full border border-neutral-300 bg-white"
88 | }}
89 | />
90 |
91 |
98 |
107 |
117 |
118 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 | {children}
135 |
136 | );
137 | };
138 |
--------------------------------------------------------------------------------
/src/components/utils/cn.ts:
--------------------------------------------------------------------------------
1 | import { ClassValue, clsx } from "clsx";
2 | import { twMerge } from "tailwind-merge";
3 |
4 | export function cn(...inputs: ClassValue[]) {
5 | return twMerge(clsx(inputs));
6 | }
--------------------------------------------------------------------------------
/tailwind.config.ts:
--------------------------------------------------------------------------------
1 | import type { Config } from "tailwindcss";
2 |
3 | const config: Config = {
4 | content: [
5 | "./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
6 | "./src/components/**/*.{js,ts,jsx,tsx,mdx}",
7 | "./src/app/**/*.{js,ts,jsx,tsx,mdx}"
8 | ],
9 | darkMode: "class",
10 | theme: {
11 | extend: {
12 | fontFamily: {
13 | sans: ["var(--font-montserrat)", "sans-serif"] // Adding Montserrat as the default sans font
14 | },
15 | backgroundImage: {
16 | "gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
17 | "gradient-conic":
18 | "conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))"
19 | },
20 | animation: {
21 | shimmer: "shimmer 2s linear infinite"
22 | },
23 | keyframes: {
24 | shimmer: {
25 | from: {
26 | backgroundPosition: "0 0"
27 | },
28 | to: {
29 | backgroundPosition: "-200% 0"
30 | }
31 | }
32 | }
33 | }
34 | },
35 | plugins: []
36 | };
37 | export default config;
38 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "lib": [
4 | "dom",
5 | "dom.iterable",
6 | "esnext"
7 | ],
8 | "allowJs": true,
9 | "skipLibCheck": true,
10 | "strict": true,
11 | "noEmit": true,
12 | "esModuleInterop": true,
13 | "module": "esnext",
14 | "moduleResolution": "bundler",
15 | "resolveJsonModule": true,
16 | "isolatedModules": true,
17 | "jsx": "preserve",
18 | "incremental": true,
19 | "plugins": [
20 | {
21 | "name": "next"
22 | }
23 | ],
24 | "paths": {
25 | "@/*": [
26 | "./src/*"
27 | ]
28 | },
29 | "target": "ES2017"
30 | },
31 | "include": [
32 | "next-env.d.ts",
33 | "**/*.ts",
34 | "**/*.tsx",
35 | ".next/types/**/*.ts"
36 | ],
37 | "exclude": [
38 | "node_modules"
39 | ]
40 | }
41 |
--------------------------------------------------------------------------------