diff --git a/.env b/.env new file mode 100644 index 0000000..3d97b50 --- /dev/null +++ b/.env @@ -0,0 +1,4 @@ +NEXT_PUBLIC_GITHUB_USERNAME=IMXNOOBX # Your GitHub username + +# General settings +CACHE_TIME=86400 # 1 day \ No newline at end of file diff --git a/.env.template b/.env.template new file mode 100644 index 0000000..e69de29 diff --git a/app/components/intro/index.tsx b/app/components/intro/index.tsx deleted file mode 100644 index ac5374c..0000000 --- a/app/components/intro/index.tsx +++ /dev/null @@ -1,44 +0,0 @@ -"use client"; -import React, { useEffect, useState } from "react"; - -import Link from "next/link"; -import Image from "next/image"; - -const Intro = () => { - const [loaded, setLoaded] = useState(false); - - useEffect(() => { - const timer = setTimeout(() => { - setLoaded(true); - }, 500); - - return () => clearTimeout(timer); - }, []); - - return ( -
-

IMXNOOBX

-

Welcome to my website

- - - -
- ); -}; - -export default Intro; \ No newline at end of file diff --git a/app/components/intro/layout.tsx b/app/components/intro/layout.tsx new file mode 100644 index 0000000..c7ec534 --- /dev/null +++ b/app/components/intro/layout.tsx @@ -0,0 +1,18 @@ +import type { Metadata } from "next"; + +export const metadata: Metadata = { + title: "Universe", + description: "With great power comes great responsibility.", +}; + +export default function IntroLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( +
+ {children} +
+ ); +} diff --git a/app/components/intro/page.tsx b/app/components/intro/page.tsx new file mode 100644 index 0000000..17e24ab --- /dev/null +++ b/app/components/intro/page.tsx @@ -0,0 +1,34 @@ +import React from "react"; + +import Link from "next/link"; +import Image from "next/image"; + +import UserCard from "@/app/components/userinfo/page"; +import { MotionDiv } from "../utils/animation"; + +export default async function Intro() { + return ( +
+ +

IMXNOOBX

+

Welcome to my portfolio

+
+ + +
+ ); +}; \ No newline at end of file diff --git a/app/components/layout/index.tsx b/app/components/layout/index.tsx index 34b950f..b5ef973 100644 --- a/app/components/layout/index.tsx +++ b/app/components/layout/index.tsx @@ -1,7 +1,7 @@ "use client"; import React, { useEffect, useState } from "react"; -const Layout = () => { +export default function Layout() { const [loaded, setLoaded] = useState(false); useEffect(() => { @@ -19,4 +19,3 @@ const Layout = () => { ); }; -export default Layout; \ No newline at end of file diff --git a/app/components/navbar/index.tsx b/app/components/navbar/index.tsx index fd0ca23..9c2ceac 100644 --- a/app/components/navbar/index.tsx +++ b/app/components/navbar/index.tsx @@ -1,6 +1,7 @@ "use client"; import React, { useEffect, useState } from "react"; +import { motion } from 'framer-motion'; import Link from "next/link"; import Image from "next/image"; import Profile from "./profiles"; @@ -19,113 +20,161 @@ import Home from "@/public/assets/home.png"; import Menu from "@/public/assets/menu.png" -const Navbar = () => { - const [loaded, setLoaded] = useState(false); +const threshold = 70; +export default function Navbar() { + // const [loaded, setLoaded] = useState(false); const [navOpen, setNavOpen] = useState(false); + const [scrolled, setScrolled] = useState(false); useEffect(() => { - const timer = setTimeout(() => { - setLoaded(true); - }, 500); - - return () => clearTimeout(timer); - }, []); + const handleScroll = () => { + if (window.scrollY >= threshold) { + setScrolled(true); + } else { + setScrolled(false); + } + }; + + window.addEventListener("scroll", handleScroll); + + return () => { + window.removeEventListener("scroll", handleScroll); + }; + }, [threshold]); return ( ); -}; - -export default Navbar; +}; \ No newline at end of file diff --git a/app/components/navbar/navlink/index.tsx b/app/components/navbar/navlink/index.tsx index a7b9d6e..909448c 100644 --- a/app/components/navbar/navlink/index.tsx +++ b/app/components/navbar/navlink/index.tsx @@ -2,7 +2,7 @@ import React from "react"; import Link from "next/link"; import Image from "next/image"; -const Button = ({ image, to, className, children }: { image: any, to: any, className: string, children: React.ReactNode }) => { +export default function Button({ image, to, className, children }: { image: any, to: any, className: string, children: React.ReactNode }) { return (
@@ -13,6 +13,4 @@ const Button = ({ image, to, className, children }: { image: any, to: any, class
); -}; - -export default Button; \ No newline at end of file +}; \ No newline at end of file diff --git a/app/components/navbar/profiles/index.tsx b/app/components/navbar/profiles/index.tsx index 9a87d85..7b86bb4 100644 --- a/app/components/navbar/profiles/index.tsx +++ b/app/components/navbar/profiles/index.tsx @@ -1,16 +1,12 @@ import React from "react"; import Link from "next/link"; import Image from "next/image"; -// import Icon from "@/public/assets/vercel.svg"; -// import Github from "@/public/assets/github.svg"; -// import Discord from "@/public/assets/discord.svg"; -// import Openlayout from "@/public/assets/openlayout.svg"; const Profile = ({ pfp, applicationp, className, full }: { pfp: any, applicationp: any, className: string, full: boolean }) => { return (
icon - icon + icon
); }; diff --git a/app/components/userinfo/error.tsx b/app/components/userinfo/error.tsx new file mode 100644 index 0000000..2a5ab06 --- /dev/null +++ b/app/components/userinfo/error.tsx @@ -0,0 +1,28 @@ +"use client"; +import React from "react"; + +export default function Error({ + error, + reset, + }: { + error: Error & { digest?: string } + reset: () => void + }) { + + return ( + + ); +}; \ No newline at end of file diff --git a/app/components/userinfo/loading.tsx b/app/components/userinfo/loading.tsx new file mode 100644 index 0000000..3c55b8c --- /dev/null +++ b/app/components/userinfo/loading.tsx @@ -0,0 +1,24 @@ +import React from "react"; + +import Link from "next/link"; +import Image from "next/image"; +import next from "next"; + +export default async function Loading() { + return ( + + ); +}; \ No newline at end of file diff --git a/app/components/userinfo/page.tsx b/app/components/userinfo/page.tsx new file mode 100644 index 0000000..c50b285 --- /dev/null +++ b/app/components/userinfo/page.tsx @@ -0,0 +1,106 @@ +import React from "react"; +import Image from "next/image"; +import { MotionDiv } from "../utils/animation"; + + +async function getUserInfo(username: string = "") { + if (!username) + username = process.env.NEXT_PUBLIC_GITHUB_USERNAME as string; + + if (!username) + throw new Error("NEXT_PUBLIC_GITHUB_USERNAME is not set in .env or .env.local"); + + // const res = await fetch( + // `https://api.github.com/users/${username}`, + // { next: { revalidate: parseInt(process.env.CACHE_TIME || "3600") }}) + // return await res.json(); + return { + login: 'IMXNOOBX', + id: 69653071, + node_id: 'MDQ6VXNlcjY5NjUzMDcx', + avatar_url: 'https://avatars.githubusercontent.com/u/69653071?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/IMXNOOBX', + html_url: 'https://github.com/IMXNOOBX', + followers_url: 'https://api.github.com/users/IMXNOOBX/followers', + following_url: 'https://api.github.com/users/IMXNOOBX/following{/other_user}', + gists_url: 'https://api.github.com/users/IMXNOOBX/gists{/gist_id}', + starred_url: 'https://api.github.com/users/IMXNOOBX/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/IMXNOOBX/subscriptions', + organizations_url: 'https://api.github.com/users/IMXNOOBX/orgs', + repos_url: 'https://api.github.com/users/IMXNOOBX/repos', + events_url: 'https://api.github.com/users/IMXNOOBX/events{/privacy}', + received_events_url: 'https://api.github.com/users/IMXNOOBX/received_events', + type: 'User', + site_admin: false, + name: 'IMXNOOBX', + company: 'Academy Of Life', + blog: 'https://imxnoobx.com', + location: 'Earth', + email: null, + hireable: null, + bio: '• hey hi! hope you have a great day! •ᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠ \r\n' + + '•> Hiii im noob!ᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠᅠ•> If you need help dm me <3', + twitter_username: null, + public_repos: 25, + public_gists: 0, + followers: 64, + following: 25, + created_at: '2020-08-13T21:26:43Z', + updated_at: '2024-03-11T06:46:08Z' + } +} + +export default async function UserCard() { + const userInfo = await getUserInfo(); + + if (!userInfo) + throw new Error("Error fetching data."); + + const clean_since = (userInfo?.created_at) ? + userInfo.created_at.split('T')[0].replace(/-/g, "/") : + "very long ago"; + + return ( + + {/* Credits to https://uiverse.io/Yaya12085/soft-jellyfish-99 */} + + + ); +}; \ No newline at end of file diff --git a/app/components/utils/CatFollow.tsx b/app/components/utils/CatFollow.tsx new file mode 100644 index 0000000..eca9c1b --- /dev/null +++ b/app/components/utils/CatFollow.tsx @@ -0,0 +1,127 @@ +"use client"; +import React, { use, useEffect, useState } from "react"; +import { m, motion } from 'framer-motion'; + +import Image from "next/image"; + +import Cat from "@/public/assets/cattopfp.jpg"; + +const cat_size = 32; +const cat_distance = 10; +let mouse_timer: NodeJS.Timeout; +const states = ['following', 'going', 'sleeping']; +export default function CatFollow() { + const [catPos, setCatPos] = useState({ x: -32, y: -32 }); + const [mousePos, setMousePos] = useState({ x: 0, y: 0 }); + const [state, setState] = useState(states[0]); + + const getCatImage = () => { + switch (state) { + case 'following': + return Cat; + case 'going': + return Cat; + case 'sleeping': + return Cat; + default: + return Cat; + } + } + + /* Handle Mouse Position */ + useEffect(() => { + const handleMove = (e: MouseEvent) => { + // setState('following'); + setMousePos({ x: e.pageX, y: e.pageY }); + + clearTimeout(mouse_timer); + + mouse_timer = setTimeout(() => { + setState('sleeping'); + }, 5000); + }; + + const handleClick = () => { + setState('going'); + } + + window.addEventListener("mousemove", handleMove); + window.addEventListener("mouseup", handleClick); + + return () => { + window.removeEventListener("mousemove", handleMove); + window.removeEventListener("mouseup", handleClick); + }; + }, [mousePos]); + + /* Handle scrolling */ + useEffect(() => { + const handleScroll = () => { + setState('sleeping'); + }; + + window.addEventListener("scroll", handleScroll); + + return () => { + window.removeEventListener("scroll", handleScroll); + }; + }, [catPos]); + + /* Handle Cat Move */ + useEffect(() => { + const moveCatInterval = setInterval(() => { + console.log(mousePos, catPos, state); + if (mousePos.x === 0 && mousePos.y === 0) return; + + if (state === 'sleeping') { + mousePos.x = window.innerWidth - cat_size * 2; + mousePos.y = window.innerHeight + window.scrollY - cat_size; + } + + const distance = Math.sqrt( + Math.pow(mousePos.x - catPos.x, 2) + Math.pow(mousePos.y - catPos.y, 2) + ); + + if (state !== 'going' && distance < 40) return; + + const speed = 0.1; + const dx = mousePos.x - catPos.x; + const dy = mousePos.y - catPos.y; + + const x = catPos.x + dx * speed; + const y = catPos.y + dy * speed; + + setCatPos({ x, y }); + + if (state === 'going' && distance < 10) setState('following'); + }, 50); + + return () => clearInterval(moveCatInterval); + }, [mousePos, catPos, state]); + + return ( + <> + + cat + {state == 'sleeping' && ( + zZz + )} + + + ); +}; \ No newline at end of file diff --git a/app/components/utils/ScrollTo.tsx b/app/components/utils/ScrollTo.tsx new file mode 100644 index 0000000..9904d3a --- /dev/null +++ b/app/components/utils/ScrollTo.tsx @@ -0,0 +1,71 @@ +"use client"; +import React, { useEffect, useState } from "react"; +import { motion } from 'framer-motion'; + +import Image from "next/image"; +import Scroll from "@/public/assets/scroll.png"; + +const threshold = 10; +export default function ScrollTo({ point }: { point: number | undefined }) { + const [scrolled, setScrolled] = useState(false); + + useEffect(() => { + const handleScroll = () => { + if (window.scrollY >= threshold) { + setScrolled(true); + } else { + setScrolled(false); + } + }; + + // We add a delay because window is not defined on the first render + setTimeout(() => handleScroll, 1000); + + window.addEventListener("scroll", handleScroll); + + return () => { + window.removeEventListener("scroll", handleScroll); + }; + }, [threshold]); + + return ( + window.scrollTo({ top: scrolled ? 0 :point || window.innerHeight, behavior: 'smooth' })} + className="overflow-hidden absolute bottom-20 left-1/2 flex items-center justify-center w-20 h-20 cursor-pointer" + > + + scroll + + ); +}; \ No newline at end of file diff --git a/app/components/utils/animation.tsx b/app/components/utils/animation.tsx new file mode 100644 index 0000000..b2453b3 --- /dev/null +++ b/app/components/utils/animation.tsx @@ -0,0 +1,8 @@ +"use client"; + +import { motion } from 'framer-motion'; + +export const MotionDiv = motion.div; +export const MotionSpan = motion.span; +export const MotionH1 = motion.h1; +export const MotionH2 = motion.h2; diff --git a/app/globals.css b/app/globals.css index 28eb300..008a8f9 100644 --- a/app/globals.css +++ b/app/globals.css @@ -3,6 +3,7 @@ @tailwind utilities; :root { + --primary: #5D5DFF; --foreground-rgb: 0, 0, 0; --background-start-rgb: 214, 219, 220; --background-end-rgb: 255, 255, 255; @@ -34,10 +35,24 @@ body { .text-border { -webkit-text-stroke: 1px white; /* Safari */ - text-stroke: 1px white; /* other browsers */ + /* text-stroke: 1px white; other browsers */ } .text-border-2 { -webkit-text-stroke: 2px white; /* Safari */ - text-stroke: 2px white; /* other browsers */ + /* text-stroke: 2px white; other browsers */ } + +*::-webkit-scrollbar { + width: 5px; +} + +*::-webkit-scrollbar-track { + background: #000; +} + +*::-webkit-scrollbar-thumb { + background-color: var(--primary); + border-radius: 7px; + border: 1px solid #5252ff; +} \ No newline at end of file diff --git a/app/not-found.tsx b/app/not-found.tsx new file mode 100644 index 0000000..c02a980 --- /dev/null +++ b/app/not-found.tsx @@ -0,0 +1,15 @@ +// app/not-found.tsx + +import Link from 'next/link' + +export default function NotFound() { + return ( +
+
+

Not Found

+

Could not find requested resource

+ Return Home +
+
+ ) +} \ No newline at end of file diff --git a/app/page.tsx b/app/page.tsx index d19fc45..147a968 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,14 +1,75 @@ import Image from "next/image"; import Layout from "./components/layout"; -import Navbar from "./components/navbar"; -import Intro from "./components/intro"; +import Navbar from "./components/navbar"; +import Intro from "./components/intro/page"; +import ScrollTo from "./components/utils/ScrollTo"; +import CatFollow from "./components/utils/CatFollow"; export default function Home() { return ( -
+
-
- +
+ {/* */} + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
💖
+
+
+
+
+
+
); diff --git a/next.config.mjs b/next.config.mjs index 4678774..07f975b 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,4 +1,13 @@ /** @type {import('next').NextConfig} */ -const nextConfig = {}; +const nextConfig = { + images: { + remotePatterns: [ + { + protocol: 'https', + hostname: 'avatars.githubusercontent.com', + }, + ], + }, +}; export default nextConfig; diff --git a/package-lock.json b/package-lock.json index dcdf3c4..173913b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,9 +8,11 @@ "name": "my-universe", "version": "0.1.0", "dependencies": { + "framer-motion": "^11.0.20", "next": "14.1.4", "react": "^18", - "react-dom": "^18" + "react-dom": "^18", + "sharp": "^0.33.3" }, "devDependencies": { "@types/node": "^20", @@ -57,6 +59,15 @@ "node": ">=6.9.0" } }, + "node_modules/@emnapi/runtime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.1.0.tgz", + "integrity": "sha512-gCGlE0fJGWalfy+wbFApjhKn6uoSVvopru77IPyxNKkjkaiSx2HxDS7eOYSmo9dcMIhmmIvoxiC3N9TM1c3EaA==", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -146,6 +157,437 @@ "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.3.tgz", + "integrity": "sha512-FaNiGX1MrOuJ3hxuNzWgsT/mg5OHG/Izh59WW2mk1UwYHUwtfbhk5QNKYZgxf0pLOhx9ctGiGa2OykD71vOnSw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "glibc": ">=2.26", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.0.2" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.33.3", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.3.tgz", + "integrity": "sha512-2QeSl7QDK9ru//YBT4sQkoq7L0EAJZA3rtV+v9p8xTKl4U1bUqTIaCnoC7Ctx2kCjQgwFXDasOtPTCT8eCTXvw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "glibc": ">=2.26", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.0.2" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.2.tgz", + "integrity": "sha512-tcK/41Rq8IKlSaKRCCAuuY3lDJjQnYIW1UXU1kxcEKrfL8WR7N6+rzNoOxoQRJWTAECuKwgAHnPvqXGN8XfkHA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "macos": ">=11", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.2.tgz", + "integrity": "sha512-Ofw+7oaWa0HiiMiKWqqaZbaYV3/UGL2wAPeLuJTx+9cXpCRdvQhCLG0IH8YGwM0yGWGLpsF4Su9vM1o6aer+Fw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "macos": ">=10.13", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.2.tgz", + "integrity": "sha512-iLWCvrKgeFoglQxdEwzu1eQV04o8YeYGFXtfWU26Zr2wWT3q3MTzC+QTCO3ZQfWd3doKHT4Pm2kRmLbupT+sZw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.28", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.2.tgz", + "integrity": "sha512-x7kCt3N00ofFmmkkdshwj3vGPCnmiDh7Gwnd4nUwZln2YjqPxV1NlTyZOvoDWdKQVDL911487HOueBvrpflagw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.26", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.2.tgz", + "integrity": "sha512-cmhQ1J4qVhfmS6szYW7RT+gLJq9dH2i4maq+qyXayUSn9/3iY2ZeWpbAgSpSVbV2E1JUL2Gg7pwnYQ1h8rQIog==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.28", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.2.tgz", + "integrity": "sha512-E441q4Qdb+7yuyiADVi5J+44x8ctlrqn8XgkDTwr4qPJzWkaHwD489iZ4nGDgcuya4iMN3ULV6NwbhRZJ9Z7SQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.26", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.2.tgz", + "integrity": "sha512-3CAkndNpYUrlDqkCM5qhksfE+qSIREVpyoeHIU6jd48SJZViAmznoQQLAv4hVXF7xyUB9zf+G++e2v1ABjCbEQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "musl": ">=1.2.2", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.2.tgz", + "integrity": "sha512-VI94Q6khIHqHWNOh6LLdm9s2Ry4zdjWJwH56WoiJU7NTeDwyApdZZ8c+SADC8OH98KWNQXnE01UdJ9CSfZvwZw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "musl": ">=1.2.2", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.33.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.3.tgz", + "integrity": "sha512-Q7Ee3fFSC9P7vUSqVEF0zccJsZ8GiiCJYGWDdhEjdlOeS9/jdkyJ6sUSPj+bL8VuOYFSbofrW0t/86ceVhx32w==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.28", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.0.2" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.33.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.3.tgz", + "integrity": "sha512-Zf+sF1jHZJKA6Gor9hoYG2ljr4wo9cY4twaxgFDvlG0Xz9V7sinsPp8pFd1XtlhTzYo0IhDbl3rK7P6MzHpnYA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.26", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.0.2" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.33.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.3.tgz", + "integrity": "sha512-vFk441DKRFepjhTEH20oBlFrHcLjPfI8B0pMIxGm3+yilKyYeHEVvrZhYFdqIseSclIqbQ3SnZMwEMWonY5XFA==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.28", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.0.2" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.33.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.3.tgz", + "integrity": "sha512-Q4I++herIJxJi+qmbySd072oDPRkCg/SClLEIDh5IL9h1zjhqjv82H0Seupd+q2m0yOfD+/fJnjSoDFtKiHu2g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.26", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.0.2" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.33.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.3.tgz", + "integrity": "sha512-qnDccehRDXadhM9PM5hLvcPRYqyFCBN31kq+ErBSZtZlsAc1U4Z85xf/RXv1qolkdu+ibw64fUDaRdktxTNP9A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "musl": ">=1.2.2", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.0.2" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.33.3", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.3.tgz", + "integrity": "sha512-Jhchim8kHWIU/GZ+9poHMWRcefeaxFIs9EBqf9KtcC14Ojk6qua7ghKiPs0sbeLbLj/2IGBtDcxHyjCdYWkk2w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "musl": ">=1.2.2", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.0.2" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.33.3", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.3.tgz", + "integrity": "sha512-68zivsdJ0koE96stdUfM+gmyaK/NcoSZK5dV5CAjES0FUXS9lchYt8LAB5rTbM7nlWtxaU/2GON0HVN6/ZYJAQ==", + "cpu": [ + "wasm32" + ], + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.1.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.33.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.3.tgz", + "integrity": "sha512-CyimAduT2whQD8ER4Ux7exKrtfoaUiVr7HG0zZvO0XTFn2idUWljjxv58GxNTkFb8/J9Ub9AqITGkJD6ZginxQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.33.3", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.3.tgz", + "integrity": "sha512-viT4fUIDKnli3IfOephGnolMzhz5VaTvDRkYqtZxOMIoMQ4MrAziO7pT1nVnOt2FAm7qW5aa+CCc13aEY6Le0g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -1166,11 +1608,22 @@ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -1181,8 +1634,16 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } }, "node_modules/commander": { "version": "4.1.1", @@ -1354,6 +1815,14 @@ "node": ">=6" } }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "engines": { + "node": ">=8" + } + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -2165,6 +2634,30 @@ "url": "https://github.com/sponsors/rawify" } }, + "node_modules/framer-motion": { + "version": "11.0.20", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.0.20.tgz", + "integrity": "sha512-YSDmWznt3hpdERosbE0UAPYWoYhTnmQ0J1qWPsgpCia9NgY8Xsz5IpOiUEGGj/nzCAW29fSrWugeLRkdp5de7g==", + "dependencies": { + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2561,6 +3054,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, "node_modules/is-async-function": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", @@ -4053,7 +4551,6 @@ "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -4068,7 +4565,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -4108,6 +4604,45 @@ "node": ">= 0.4" } }, + "node_modules/sharp": { + "version": "0.33.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.3.tgz", + "integrity": "sha512-vHUeXJU1UvlO/BNwTpT0x/r53WkLUVxrmb5JTgW92fdFCFk0ispLMAeu/jPO2vjkXM1fYUi3K7/qcLF47pwM1A==", + "hasInstallScript": true, + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.3", + "semver": "^7.6.0" + }, + "engines": { + "libvips": ">=8.15.2", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.33.3", + "@img/sharp-darwin-x64": "0.33.3", + "@img/sharp-libvips-darwin-arm64": "1.0.2", + "@img/sharp-libvips-darwin-x64": "1.0.2", + "@img/sharp-libvips-linux-arm": "1.0.2", + "@img/sharp-libvips-linux-arm64": "1.0.2", + "@img/sharp-libvips-linux-s390x": "1.0.2", + "@img/sharp-libvips-linux-x64": "1.0.2", + "@img/sharp-libvips-linuxmusl-arm64": "1.0.2", + "@img/sharp-libvips-linuxmusl-x64": "1.0.2", + "@img/sharp-linux-arm": "0.33.3", + "@img/sharp-linux-arm64": "0.33.3", + "@img/sharp-linux-s390x": "0.33.3", + "@img/sharp-linux-x64": "0.33.3", + "@img/sharp-linuxmusl-arm64": "0.33.3", + "@img/sharp-linuxmusl-x64": "0.33.3", + "@img/sharp-wasm32": "0.33.3", + "@img/sharp-win32-ia32": "0.33.3", + "@img/sharp-win32-x64": "0.33.3" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -4159,6 +4694,14 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -4928,8 +5471,7 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yaml": { "version": "2.4.1", diff --git a/package.json b/package.json index f0ff945..4d91c66 100644 --- a/package.json +++ b/package.json @@ -3,25 +3,27 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "next dev", + "dev": "next dev --turbo", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { + "framer-motion": "^11.0.20", + "next": "14.1.4", "react": "^18", "react-dom": "^18", - "next": "14.1.4" + "sharp": "^0.33.3" }, "devDependencies": { - "typescript": "^5", "@types/node": "^20", "@types/react": "^18", "@types/react-dom": "^18", "autoprefixer": "^10.0.1", + "eslint": "^8", + "eslint-config-next": "14.1.4", "postcss": "^8", "tailwindcss": "^3.3.0", - "eslint": "^8", - "eslint-config-next": "14.1.4" + "typescript": "^5" } } diff --git a/public/assets/scroll.png b/public/assets/scroll.png new file mode 100644 index 0000000..7fdffcf Binary files /dev/null and b/public/assets/scroll.png differ