Merge pull request #8 from MealCraft/feature/into_the_unknown

Feature/into the unknown
This commit is contained in:
Jun-te Kim 2025-12-07 12:54:44 +00:00 committed by GitHub
commit 7b1d007ff4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 282 additions and 7 deletions

View file

@ -4,7 +4,7 @@ TODO:
- [x] Set up new laptop github workflow - [x] Set up new laptop github workflow
- [x] Download next js - [x] Download next js
- [x] Aws terraform plan and apply configured - [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] k get pods -A works
- [x] deploy docker registry credentials - [x] deploy docker registry credentials
- [x] deploy storageclass - [x] deploy storageclass
@ -13,4 +13,8 @@ TODO:
- [x] deploy next js to juntekim.com - [x] deploy next js to juntekim.com
- [x] Traefik certs change from staging to production - [x] Traefik certs change from staging to production
- [x] Merge my code to main - [x] Merge my code to main
- [x] Push from workflow k8s bootstrap - [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

View file

@ -0,0 +1,3 @@
export default function About() {
return <h1>Everything you need to know about me will be here</h1>;
}

View file

@ -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 (
<div className="p-6 font-mono text-red-400">
404 - File not found: /{filePath}
</div>
);
}
// If it's a folder, list its contents
if (fs.lstatSync(fullPath).isDirectory()) {
const files = fs.readdirSync(fullPath);
return (
<div className="p-6 font-mono text-green-400">
<h2 className="mb-4 text-xl font-bold text-zinc-200">/{filePath}</h2>
{files.map((name) => (
<div key={name}>- {name}</div>
))}
</div>
);
}
// Read file contents
const content = fs.readFileSync(fullPath, "utf8");
return (
<div className="p-6 font-mono text-green-400 whitespace-pre-wrap">
<h2 className="mb-4 text-xl font-bold text-zinc-200">/{filePath}</h2>
{content}
</div>
);
}

View file

@ -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 = () => (
<div className="text-green-400 font-mono mt-2">
compiling {loaderProgress}%
<div className="w-full bg-zinc-800 h-2 rounded mt-1">
<div
className="bg-green-500 h-2 rounded"
style={{ width: `${loaderProgress}%` }}
/>
</div>
</div>
);
return (
<div
className="rounded-lg border border-zinc-700 bg-black text-zinc-100 p-4 font-mono text-sm shadow-xl w-full max-w-2xl"
style={{ whiteSpace: "pre-wrap" }}
>
{/* Prompt 1 */}
{showFirstPrompt && <div className="text-green-400">juntekim@site:~$</div>}
{/* Enter echo */}
{showEnterEcho && <div className="text-green-400">juntekim@site:~$</div>}
{/* Command 1 (NO cursor here) */}
{typedCommand1 && (
<div className="text-green-400">{typedCommand1}</div>
)}
{/* Quote */}
{showQuote && (
<div className="text-zinc-300 italic my-2 animate-fadeIn">{quote}</div>
)}
{/* Command 2 (NO cursor here) */}
{typedCommand2 && (
<div className="text-green-400">{typedCommand2}</div>
)}
{/* Loader */}
{showLoader && <LoaderBar />}
{/* Final tree */}
{showTree && (
<div className="animate-fadeIn mt-2 text-green-400">
/
<div className="ml-2">{children}</div>
{/* Final Prompt WITH cursor */}
<div className="text-green-400 mt-2">
juntekim@site:~$ <span className="animate-pulse"></span>
</div>
</div>
)}
</div>
);
}

View file

@ -24,3 +24,12 @@ body {
color: var(--foreground); color: var(--foreground);
font-family: Arial, Helvetica, sans-serif; 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;
}

View file

@ -1,11 +1,28 @@
import Image from "next/image"; import TerminalBox from "./components/TerminalBox";
import { getRouteTree, RouteNode } from "../lib/routeTree";
export default function Home() { export default function Home() {
const routes = getRouteTree();
function renderTree(nodes: RouteNode[], depth = 0) {
return nodes.map((node, i) => (
<div key={node.path}>
<div style={{ marginLeft: depth * 16 }}>
<a href={node.path} className="text-green-400 hover:underline">
{depth === 0 ? "├── " : "│ ".repeat(depth) + "└── "}
{node.name}
</a>
</div>
{node.children && renderTree(node.children, depth + 1)}
</div>
));
}
return ( return (
<div className="flex h-screen flex-col items-center justify-center space-y-6"> <div className="flex min-h-screen items-center justify-center p-10">
<h1 className="text-3xl font-bold text-center"> <TerminalBox>
Impatient with actions, Patient with results {renderTree(routes)}
</h1> </TerminalBox>
</div> </div>
); );
} }

View file

@ -0,0 +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 dont know if it happened for the best — but I know Ill make the best out of whatever happens.” - Unknown',
];

View file

@ -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, "");
}