feat: name animation
Signed-off-by: Ameya Shenoy <shenoy.ameya@gmail.com>
This commit is contained in:
parent
f12356ae66
commit
d385af6afe
12 changed files with 320 additions and 8 deletions
1
frontend/package-lock.json
generated
1
frontend/package-lock.json
generated
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
24
frontend/src/app/blog/[slug]/page.tsx
Normal file
24
frontend/src/app/blog/[slug]/page.tsx
Normal file
|
|
@ -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 (
|
||||
<main className="flex items-center justify-center h-screen">
|
||||
<div className="w-[95vw]" dangerouslySetInnerHTML={{ __html: content }} />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
// 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 } };
|
||||
// };
|
||||
178
frontend/src/app/blog/content/docker_primer.md
Normal file
178
frontend/src/app/blog/content/docker_primer.md
Normal file
|
|
@ -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
|
||||
```
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
export default function Blog() {
|
||||
return (
|
||||
<main className="flex items-center justify-center h-screen">
|
||||
This is blog list page
|
||||
This is blogs index page
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
>
|
||||
<div className="min-h-screen">
|
||||
<GSAPCursor />
|
||||
<NavigationMenu />
|
||||
{children}
|
||||
<footer className="flex"></footer>
|
||||
|
|
|
|||
45
frontend/src/components/CustomCircleCursor.tsx
Normal file
45
frontend/src/components/CustomCircleCursor.tsx
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
"use client";
|
||||
import { useRef, useEffect, FC } from "react";
|
||||
import gsap from "gsap";
|
||||
|
||||
const GSAPCursor: FC = () => {
|
||||
const cursorRef = useRef<HTMLDivElement>(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 (
|
||||
<div
|
||||
ref={cursorRef}
|
||||
className="fixed w-8 h-8 rounded-full border-2 border-dotted border-red-500 bg-transparent pointer-events-none z-50"
|
||||
style={{
|
||||
transform: "translate(-50%, -50%)",
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default GSAPCursor;
|
||||
|
|
@ -4,7 +4,7 @@ export function NameComponent() {
|
|||
return (
|
||||
<div className="flex justify-center font-[family-name:var(--font-spacegrotesk-sans)] font-semibold text-fluid tracking-tighter">
|
||||
<TextScramble
|
||||
firstName="Ameya"
|
||||
firstName="Ameya "
|
||||
lastName="Shenoy"
|
||||
onlineHandleFirstName="coding"
|
||||
onlineHandleLastName="coffee"
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ export function World() {
|
|||
const pillsToRenderInfo = [
|
||||
{ text: "ENGINEERING MANAGER" },
|
||||
{ text: "PRINCIPAL ENGINEER" },
|
||||
{ text: "NIX", chamferRadius: convertRemToPixels(1.25) },
|
||||
{ text: "NIX *", chamferRadius: convertRemToPixels(1.25) },
|
||||
{ text: "AI", chamferRadius: convertRemToPixels(1.25) },
|
||||
];
|
||||
|
||||
|
|
@ -254,10 +254,15 @@ export function World() {
|
|||
}, [resolvedTheme, dimensions]);
|
||||
|
||||
return (
|
||||
// TODO: ask Shubh why does my name spawn at the top and then shift down
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="h-[40vh] mx-auto relative overflow-hidden"
|
||||
className="h-[40vh] border-red-500 border-2"
|
||||
style={{ width: `${viewportWidthPercent}vw` }}
|
||||
/>
|
||||
>
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="h-full w-full mx-auto relative overflow-hidden"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<TextScrambleProps> = ({
|
|||
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<TextScrambleProps> = ({
|
|||
if (counter >= end) complete++;
|
||||
}
|
||||
|
||||
setFunctiono(output);
|
||||
setFunction(output);
|
||||
if (complete < length) {
|
||||
requestAnimationFrame(update);
|
||||
counter++;
|
||||
|
|
@ -78,6 +79,26 @@ const TextScramble: React.FC<TextScrambleProps> = ({
|
|||
}
|
||||
}, [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 (
|
||||
<div
|
||||
className="group relative font-mono transition-all duration-300"
|
||||
|
|
|
|||
18
frontend/src/hooks/useIsMobile.tsx
Normal file
18
frontend/src/hooks/useIsMobile.tsx
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import { useState, useEffect } from "react";
|
||||
|
||||
export const useIsMobile = () => {
|
||||
const [isMobile, setIsMobile] = useState<boolean>(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;
|
||||
};
|
||||
16
frontend/src/lib/markdown.ts
Normal file
16
frontend/src/lib/markdown.ts
Normal file
|
|
@ -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();
|
||||
}
|
||||
Loading…
Reference in a new issue