From d385af6afed726560a2d07a2f1e3e75b280df7e1 Mon Sep 17 00:00:00 2001 From: Ameya Shenoy Date: Sun, 8 Jun 2025 19:55:32 +0530 Subject: [PATCH] feat: name animation Signed-off-by: Ameya Shenoy --- frontend/package-lock.json | 1 + frontend/package.json | 1 + frontend/src/app/blog/[slug]/page.tsx | 24 +++ .../src/app/blog/content/docker_primer.md | 178 ++++++++++++++++++ frontend/src/app/blog/page.tsx | 3 +- frontend/src/app/layout.tsx | 2 + .../src/components/CustomCircleCursor.tsx | 45 +++++ frontend/src/components/NameComponent.tsx | 2 +- frontend/src/components/PhysicsSimulation.tsx | 13 +- frontend/src/components/TextScramble.tsx | 25 ++- frontend/src/hooks/useIsMobile.tsx | 18 ++ frontend/src/lib/markdown.ts | 16 ++ 12 files changed, 320 insertions(+), 8 deletions(-) create mode 100644 frontend/src/app/blog/[slug]/page.tsx create mode 100644 frontend/src/app/blog/content/docker_primer.md create mode 100644 frontend/src/components/CustomCircleCursor.tsx create mode 100644 frontend/src/hooks/useIsMobile.tsx create mode 100644 frontend/src/lib/markdown.ts diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 789f0f2..af3ff22 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -12,6 +12,7 @@ "@radix-ui/react-slot": "^1.2.3", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "gsap": "^3.13.0", "lucide-react": "^0.511.0", "matter-js": "^0.20.0", "next": "15.3.3", diff --git a/frontend/package.json b/frontend/package.json index f03717a..47ef107 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -13,6 +13,7 @@ "@radix-ui/react-slot": "^1.2.3", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "gsap": "^3.13.0", "lucide-react": "^0.511.0", "matter-js": "^0.20.0", "next": "15.3.3", diff --git a/frontend/src/app/blog/[slug]/page.tsx b/frontend/src/app/blog/[slug]/page.tsx new file mode 100644 index 0000000..fdae6ae --- /dev/null +++ b/frontend/src/app/blog/[slug]/page.tsx @@ -0,0 +1,24 @@ +import { GetStaticPaths, GetStaticProps } from "next"; +import { getMarkdownContent } from "@/lib/markdown"; + +export default async function BlogPost() { + const content = await getMarkdownContent(`docker_primer.md`); + + return ( +
+
+
+ ); +} + +// export const getStaticPaths: GetStaticPaths = async () => { +// // Here you would fetch the list of markdown files to create paths +// const paths = [{ params: { slug: "example" } }]; // Example path +// return { paths, fallback: false }; +// }; +// +// export const getStaticProps: GetStaticProps = async ({ params }) => { +// console.log(params?.slug); +// const content = await getMarkdownContent(`docker_primer.md`); +// return { props: { content } }; +// }; diff --git a/frontend/src/app/blog/content/docker_primer.md b/frontend/src/app/blog/content/docker_primer.md new file mode 100644 index 0000000..d3910ba --- /dev/null +++ b/frontend/src/app/blog/content/docker_primer.md @@ -0,0 +1,178 @@ +--- +title: Docker Primer +date: 2018-02-13T13:56:12-05:00 +tags: ["docker", "containers"] +type: Docker +summary: Docker basics to get you started +--- + +When we think of virtualization today, we may think of Virtual Box, which abstracts away the system processes, and lets you run a completely system from another. Think of Docker as Virtual Box, but extremely lightweight (in terms of resource consumption). Obviously I'm over simplifying the explanation a little, and a whole of things are getting lost in simplification. But for now, this will do. + +## Installation + +- Install docker + +```shell +apt remove docker docker-engine docker.io +apt update && apt -y upgrade +apt install -y linux-image-extra-$(uname -r) linux-image-extra-virtual #FOR UBUNTU 18: apt install -y linux-image-$(uname -r) linux-image-extra-virtual +apt update && apt -y upgrade +apt install -y apt-transport-https ca-certificates curl software-properties-common +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - +add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" #FOR UBUNTU 18: instead of stable use edge (just for now, since they haven't released the stable version on 18.04 yet) +apt update && apt -y upgrade +apt install -y docker-ce +``` + +- Install docker-compose + +```shell +curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose #use the latest docker-compose version, by looking at releases on github pages [https://github.com/docker/compose/releases]https://gist.githubusercontent.com/mamigot/1abdefc684f97d3476f177d85248ff36/raw/5f57b4918b237f8e0127b45984fa51a483218349/docker-compose.yml +chmod +x /usr/local/bin/docker-compose +``` + +## Post Installation stuff + +Allow docker usage without sudo access + +The docker daemon binds to a Unix socket instead of a TCP port. By +default that Unix socket is owned by the user root and other users can +only access it using sudo. The docker daemon always runs as the root +user. To prevent using sudo when you use the docker command, create a +Unix group called docker and add users to it. When the docker daemon +starts, it makes the ownership of the Unix socket read/writable by the +docker group + +```shell +sudo groupadd docker +sudo usermod -aG docker $USER +newgrp docker +``` + +## Terminology + +- Images + +Images are read only We upload images to hub. Think of them as classes in an object oriented programming language terminology. + +- Containers + +Containers boot up from images. Think of them as instances of a class. + +- Tags + +You can think of this as versions + +- Container ID or Image ID + +Unique ID assigned to every container or image respectively + +## Usage + +- A `Dockerfile` can be used to build docker images + +- To list all images available on your system + +```shell +docker images +``` + +- To list all containers + +```shell +docker ps -a +``` + +- To pull images from the docker hub, for example for pulling the + ubuntu image + +```shell +docker pull ubuntu +``` + +By default the `latest` `tag` is pulled. Consider `tag` to be sort of like the version of the image you want. + +- To pull a specific tag, lets say the `tag` is `12.04` + +```shell +docker pull ubuntu:12.04 +``` + +- To delete an image + +```shell +docker rmi ubuntu:latest +``` + +or + +```shell +docker rmi IMAGE_ID +``` + +- To create a `container` from an `image` and run it + +```shell +docker run -it ID /bin/bash +``` + +- `i` stands for interactive +- `t` stands for pseudo tty. It is for specifying the path to the shell to be run. +- `ID` can be an `IMAGE-ID` or a `CONTAINER-ID` obtained by listing all images, or containers respectively. + +Note: Every time you use `docker run` using the IMAGE-ID, a new +container is created based on the `image` + +Extra bits: If the argument `--rm` is if passed, causes the container to automatically get deleted after exiting the shell. + +- To exit a container + +```shell +exit +``` + +- To start a container + +```shell +docker start CONTAINER_ID +``` + +- To stop a container + +```shell +docker stop CONTAINER_ID +``` + +- To delete a container + +```shell +docker rm CONTAINER_ID +``` + +- To build your own docker image using a `Dockerfile`. Create a `Dockerfile` and put it in a folder, and execute the following command + +```shell +docker build -t username/image_name:image_tag . +``` + +`username` - as on hub.docker.com +`image_name` - the name of the image you want to build +`image_tag` - the tag you want to assign to the image + +- To delete dangling images (unused images present on your system) + +```shell +docker rmi $(docker images -f dangling=true -q) +``` + +- Save an existing docker container as an image + +```shell +docker commit CONTAINER_ID IMAGE_NAME:IMAGE_TAG +``` + +- Saving an image as a tar file + +```shell +docker save IMAGE_ID -o file_name.tar +``` diff --git a/frontend/src/app/blog/page.tsx b/frontend/src/app/blog/page.tsx index f71b5fa..0985da0 100644 --- a/frontend/src/app/blog/page.tsx +++ b/frontend/src/app/blog/page.tsx @@ -1,7 +1,8 @@ export default function Blog() { return (
- This is blog list page + This is blogs index page
); } + diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx index 5301dfc..a3942eb 100644 --- a/frontend/src/app/layout.tsx +++ b/frontend/src/app/layout.tsx @@ -4,6 +4,7 @@ import { Geist, Geist_Mono, Space_Grotesk, Space_Mono } from "next/font/google"; import "./globals.css"; import { NavigationMenu } from "@/components/Navbar"; +import GSAPCursor from "@/components/CustomCircleCursor"; const geistSans = Geist({ variable: "--font-geist-sans", @@ -49,6 +50,7 @@ export default function RootLayout({ disableTransitionOnChange >
+ {children}
diff --git a/frontend/src/components/CustomCircleCursor.tsx b/frontend/src/components/CustomCircleCursor.tsx new file mode 100644 index 0000000..92ea1eb --- /dev/null +++ b/frontend/src/components/CustomCircleCursor.tsx @@ -0,0 +1,45 @@ +"use client"; +import { useRef, useEffect, FC } from "react"; +import gsap from "gsap"; + +const GSAPCursor: FC = () => { + const cursorRef = useRef(null); + + // For touch devices, return null + if (typeof window !== "undefined" && "ontouchstart" in window) return null; + + useEffect(() => { + // Initialize GSAP animation + let xTo = gsap.quickTo(cursorRef.current, "x", { + duration: 2, + ease: "power2.out", + }); + let yTo = gsap.quickTo(cursorRef.current, "y", { + duration: 2, + ease: "power2.out", + }); + + const onMouseMove = (e: MouseEvent) => { + xTo(e.clientX); + yTo(e.clientY); + }; + + window.addEventListener("mousemove", onMouseMove); + + return () => { + window.removeEventListener("mousemove", onMouseMove); + }; + }, []); + + return ( +
+ ); +}; + +export default GSAPCursor; diff --git a/frontend/src/components/NameComponent.tsx b/frontend/src/components/NameComponent.tsx index 37d266d..faf7848 100644 --- a/frontend/src/components/NameComponent.tsx +++ b/frontend/src/components/NameComponent.tsx @@ -4,7 +4,7 @@ export function NameComponent() { return (
+ > +
+
); } diff --git a/frontend/src/components/TextScramble.tsx b/frontend/src/components/TextScramble.tsx index 410e2a3..5c4f100 100644 --- a/frontend/src/components/TextScramble.tsx +++ b/frontend/src/components/TextScramble.tsx @@ -1,6 +1,7 @@ "use client"; import { useState, useEffect, useCallback } from "react"; +import { useIsMobile } from "@/hooks/useIsMobile"; // Adjust the path as necessary interface TextScrambleProps { firstName: string; @@ -22,7 +23,7 @@ const TextScramble: React.FC = ({ const chars = "!<>-_\\/[]{}—=+*^?#________"; const scramble = useCallback( - (fromText: string, toText: string, setFunctiono) => { + (fromText: string, toText: string, setFunction: Function) => { let counter = 0; const length = Math.max(fromText.length, toText.length); const queue = []; @@ -56,7 +57,7 @@ const TextScramble: React.FC = ({ if (counter >= end) complete++; } - setFunctiono(output); + setFunction(output); if (complete < length) { requestAnimationFrame(update); counter++; @@ -78,6 +79,26 @@ const TextScramble: React.FC = ({ } }, [isHovering, scramble, firstName, lastName]); + const autoScramble = () => { + console.log(displayFirstName, firstName); + if (displayFirstName == firstName) { + scramble(firstName, onlineHandleFirstName, setfirstNameText); + scramble(lastName, onlineHandleLastName, setLastNameText); + } else { + scramble(displayFirstName, firstName, setfirstNameText); + scramble(displayLastNameText, lastName, setLastNameText); + } + }; + + const isMobile = useIsMobile(); + + useEffect(() => { + if (isMobile) { + const intervalID = setInterval(autoScramble, 2000); + return () => clearInterval(intervalID); + } + }, [isMobile, displayFirstName, displayLastNameText]); + return (
{ + const [isMobile, setIsMobile] = useState(false); + + useEffect(() => { + const handleResize = () => { + setIsMobile(window.innerWidth < 640); // Tailwind's mobile breakpoint + }; + + handleResize(); // Check on mount + window.addEventListener("resize", handleResize); + + return () => window.removeEventListener("resize", handleResize); + }, []); + + return isMobile; +}; diff --git a/frontend/src/lib/markdown.ts b/frontend/src/lib/markdown.ts new file mode 100644 index 0000000..d4ea7ea --- /dev/null +++ b/frontend/src/lib/markdown.ts @@ -0,0 +1,16 @@ +// utils/markdown.ts +import fs from "fs"; +import path from "path"; +import { remark } from "remark"; +import html from "remark-html"; + +const markdownDirectory = path.join(process.cwd(), "src/app/blog/content"); +console.log(markdownDirectory) + +export async function getMarkdownContent(fileName: string) { + const filePath = path.join(markdownDirectory, fileName); + const fileContents = fs.readFileSync(filePath, "utf8"); + + const processedContent = await remark().use(html).process(fileContents); + return processedContent.toString(); +}