From bf918f4d8eff20a1f65240d2d03710a773f06089 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Sun, 7 Dec 2025 12:46:59 +0000 Subject: [PATCH 1/2] frontend made more --- README.md | 8 +- juntekim_frontend/app/About/page.tsx | 3 + juntekim_frontend/app/[...path]/page.tsx | 42 ++++++ .../app/components/TerminalBox.tsx | 137 ++++++++++++++++++ juntekim_frontend/app/globals.css | 9 ++ juntekim_frontend/app/page.tsx | 27 +++- juntekim_frontend/lib/quotes.ts | 4 + juntekim_frontend/lib/routeTree.ts | 56 +++++++ 8 files changed, 279 insertions(+), 7 deletions(-) create mode 100644 juntekim_frontend/app/About/page.tsx create mode 100644 juntekim_frontend/app/[...path]/page.tsx create mode 100644 juntekim_frontend/app/components/TerminalBox.tsx create mode 100644 juntekim_frontend/lib/quotes.ts create mode 100644 juntekim_frontend/lib/routeTree.ts diff --git a/README.md b/README.md index 62423c2..8de6550 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ TODO: - [x] Set up new laptop github workflow - [x] Download next js - [x] Aws terraform plan and apply configured -- [] Deploy into my new k8s +- [x] Deploy into my new k8s - [x] k get pods -A works - [x] deploy docker registry credentials - [x] deploy storageclass @@ -13,4 +13,8 @@ TODO: - [x] deploy next js to juntekim.com - [x] Traefik certs change from staging to production - [x] Merge my code to main - - [x] Push from workflow k8s bootstrap \ No newline at end of file + - [x] Push from workflow k8s bootstrap + - [] Add my favroutie quotes in a file and everytime someone joins it shows a new one +n8n +home assistant deploy +ajay website deploy \ No newline at end of file diff --git a/juntekim_frontend/app/About/page.tsx b/juntekim_frontend/app/About/page.tsx new file mode 100644 index 0000000..d1db225 --- /dev/null +++ b/juntekim_frontend/app/About/page.tsx @@ -0,0 +1,3 @@ +export default function About() { + return

Everything you need to know about me will be here

; +} diff --git a/juntekim_frontend/app/[...path]/page.tsx b/juntekim_frontend/app/[...path]/page.tsx new file mode 100644 index 0000000..d2702fb --- /dev/null +++ b/juntekim_frontend/app/[...path]/page.tsx @@ -0,0 +1,42 @@ +import fs from "fs"; +import path from "path"; + +export default function FilePage({ params }: { params: { path?: string[] } }) { + const filePath = params.path?.join("/") || ""; + + // Resolve to actual file in public folder + const fullPath = path.join(process.cwd(), "public", filePath); + + // If folder or file missing + if (!fs.existsSync(fullPath)) { + return ( +
+ 404 - File not found: /{filePath} +
+ ); + } + + // If it's a folder, list its contents + if (fs.lstatSync(fullPath).isDirectory()) { + const files = fs.readdirSync(fullPath); + + return ( +
+

/{filePath}

+ {files.map((name) => ( +
- {name}
+ ))} +
+ ); + } + + // Read file contents + const content = fs.readFileSync(fullPath, "utf8"); + + return ( +
+

/{filePath}

+ {content} +
+ ); +} diff --git a/juntekim_frontend/app/components/TerminalBox.tsx b/juntekim_frontend/app/components/TerminalBox.tsx new file mode 100644 index 0000000..e8c27d5 --- /dev/null +++ b/juntekim_frontend/app/components/TerminalBox.tsx @@ -0,0 +1,137 @@ +"use client"; + +import { useState, useEffect } from "react"; +import { QUOTES } from "@/lib/quotes"; + +export default function TerminalBox({ children }: { children: React.ReactNode }) { + const [showFirstPrompt, setShowFirstPrompt] = useState(false); + const [showEnterEcho, setShowEnterEcho] = useState(false); + const [typedCommand1, setTypedCommand1] = useState(""); + const [showQuote, setShowQuote] = useState(false); + const [quote, setQuote] = useState(""); + const [typedCommand2, setTypedCommand2] = useState(""); + const [showLoader, setShowLoader] = useState(false); + const [loaderProgress, setLoaderProgress] = useState(0); + const [showTree, setShowTree] = useState(false); + + // INIT + useEffect(() => { + setQuote(QUOTES[Math.floor(Math.random() * QUOTES.length)]); + + setTimeout(() => setShowFirstPrompt(true), 400); + setTimeout(() => setShowEnterEcho(true), 1500); + setTimeout(() => typeCommand1(), 1800); + }, []); + + // TYPE COMMAND 1 + const typeCommand1 = () => { + const cmd = "juntekim@site:~$ quoteOfTheDay"; + let i = 0; + + const interval = setInterval(() => { + setTypedCommand1(cmd.slice(0, i + 1)); + i++; + if (i >= cmd.length) { + clearInterval(interval); + + setTimeout(() => setShowQuote(true), 300); + setTimeout(() => typeCommand2(), 1200); + } + }, 50); + }; + + // TYPE COMMAND 2 + const typeCommand2 = () => { + const cmd = "juntekim@site:~$ tree ."; + let i = 0; + + const interval = setInterval(() => { + setTypedCommand2(cmd.slice(0, i + 1)); + i++; + if (i >= cmd.length) { + clearInterval(interval); + + setTimeout(() => startLoader(), 400); + } + }, 60); + }; + + // LOADER + const startLoader = () => { + setShowLoader(true); + + let progress = 0; + const interval = setInterval(() => { + progress += Math.random() * 20; + + if (progress >= 100) { + progress = 100; + clearInterval(interval); + + setTimeout(() => { + setShowTree(true); + setShowLoader(false); + }, 500); + } + + setLoaderProgress(Math.floor(progress)); + }, 300); + }; + + // Loader UI + const LoaderBar = () => ( +
+ compiling… {loaderProgress}% +
+
+
+
+ ); + + return ( +
+ {/* Prompt 1 */} + {showFirstPrompt &&
juntekim@site:~$
} + + {/* Enter echo */} + {showEnterEcho &&
juntekim@site:~$
} + + {/* Command 1 (NO cursor here) */} + {typedCommand1 && ( +
{typedCommand1}
+ )} + + {/* Quote */} + {showQuote && ( +
{quote}
+ )} + + {/* Command 2 (NO cursor here) */} + {typedCommand2 && ( +
{typedCommand2}
+ )} + + {/* Loader */} + {showLoader && } + + {/* Final tree */} + {showTree && ( +
+ / +
{children}
+ + {/* Final Prompt WITH cursor */} +
+ juntekim@site:~$ +
+
+ )} +
+ ); +} diff --git a/juntekim_frontend/app/globals.css b/juntekim_frontend/app/globals.css index a2dc41e..54cf200 100644 --- a/juntekim_frontend/app/globals.css +++ b/juntekim_frontend/app/globals.css @@ -24,3 +24,12 @@ body { color: var(--foreground); font-family: Arial, Helvetica, sans-serif; } + +@keyframes fadeIn { + from { opacity: 0; transform: translateY(-2px); } + to { opacity: 1; transform: translateY(0); } +} + +.animate-fadeIn { + animation: fadeIn 0.4s ease forwards; +} diff --git a/juntekim_frontend/app/page.tsx b/juntekim_frontend/app/page.tsx index 2aa5eaf..8a79bc3 100644 --- a/juntekim_frontend/app/page.tsx +++ b/juntekim_frontend/app/page.tsx @@ -1,11 +1,28 @@ -import Image from "next/image"; +import TerminalBox from "./components/TerminalBox"; +import { getRouteTree, RouteNode } from "../lib/routeTree"; export default function Home() { + const routes = getRouteTree(); + + function renderTree(nodes: RouteNode[], depth = 0) { + return nodes.map((node, i) => ( +
+
+ + {depth === 0 ? "├── " : "│ ".repeat(depth) + "└── "} + {node.name} + +
+ {node.children && renderTree(node.children, depth + 1)} +
+ )); + } + return ( -
-

- Impatient with actions, Patient with results -

+
+ + {renderTree(routes)} +
); } diff --git a/juntekim_frontend/lib/quotes.ts b/juntekim_frontend/lib/quotes.ts new file mode 100644 index 0000000..612b5b6 --- /dev/null +++ b/juntekim_frontend/lib/quotes.ts @@ -0,0 +1,4 @@ +export const QUOTES = [ + '"Impatient with actions, patient with results." - Naval Ravikant', + '"What good shall I do today? - Benjamin Franklin"', +]; diff --git a/juntekim_frontend/lib/routeTree.ts b/juntekim_frontend/lib/routeTree.ts new file mode 100644 index 0000000..ad07c1e --- /dev/null +++ b/juntekim_frontend/lib/routeTree.ts @@ -0,0 +1,56 @@ +import fs from "fs"; +import path from "path"; + +export type RouteNode = { + name: string; + path: string; + children?: RouteNode[]; +}; + +export function getRouteTree(): RouteNode[] { + const appDir = path.join(process.cwd(), "app"); + + function walk(currentDir: string, baseRoute = ""): RouteNode[] { + const entries = fs.readdirSync(currentDir, { withFileTypes: true }); + + return entries + .filter((e) => { + if (!e.isDirectory()) return false; + + // EXCLUDE folders that should not be routes + if (e.name.startsWith("_")) return false; + if (e.name.startsWith("(")) return false; + if (e.name.startsWith("[")) return false; // hide [...path] + + // Only include if folder HAS a page.tsx OR contains nested route pages + const folderPath = path.join(currentDir, e.name); + const hasPage = fs.existsSync(path.join(folderPath, "page.tsx")); + + const hasNestedPages = fs + .readdirSync(folderPath) + .some((child) => { + const full = path.join(folderPath, child); + return ( + fs.lstatSync(full).isDirectory() && + fs.existsSync(path.join(full, "page.tsx")) + ); + }); + + return hasPage || hasNestedPages; + }) + .map((folder) => { + const folderPath = path.join(currentDir, folder.name); + const routePath = `${baseRoute}/${folder.name}`; + + const children = walk(folderPath, routePath); + + return { + name: folder.name, + path: routePath, + children, + }; + }); + } + + return walk(appDir, ""); +} From 330ea3787ee60db0eac5f34a3801e006c1698ce0 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Sun, 7 Dec 2025 12:53:18 +0000 Subject: [PATCH 2/2] frontend made more --- juntekim_frontend/lib/quotes.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/juntekim_frontend/lib/quotes.ts b/juntekim_frontend/lib/quotes.ts index 612b5b6..6696b13 100644 --- a/juntekim_frontend/lib/quotes.ts +++ b/juntekim_frontend/lib/quotes.ts @@ -1,4 +1,7 @@ export const QUOTES = [ '"Impatient with actions, patient with results." - Naval Ravikant', '"What good shall I do today? - Benjamin Franklin"', + '"Nothing like a health problem to turn up the contrast dial on the rest of life." - Naval Ravikant', + '"If you want to go fast go alone; if you want to go far go together" - Unknown', + '“I don’t know if it happened for the best — but I know I’ll make the best out of whatever happens.” - Unknown', ];