From 947f72ecca0e597bcf514f19cebcc8c4b894bc26 Mon Sep 17 00:00:00 2001 From: denshooter Date: Fri, 9 Jan 2026 19:24:12 +0100 Subject: [PATCH] feat: Add interactive kernel panic 404 page - Terminal-style 404 page with boot sequence - Interactive command line with file system - Easter eggs: hawkins/011, fsociety, 42, rm -rf / - CRT monitor effects and visual glitches - Audio synthesis for key presses and effects - Full terminal emulator with commands: ls, cd, cat, grep, etc. --- app/components/KernelPanic404.tsx | 703 ++++++++++++++++++++++++++++++ app/not-found.tsx | 21 +- 2 files changed, 705 insertions(+), 19 deletions(-) create mode 100644 app/components/KernelPanic404.tsx diff --git a/app/components/KernelPanic404.tsx b/app/components/KernelPanic404.tsx new file mode 100644 index 0000000..6ceae7c --- /dev/null +++ b/app/components/KernelPanic404.tsx @@ -0,0 +1,703 @@ +"use client"; + +import { useEffect, useRef, useState } from "react"; + +interface FileSystemNode { + type: 'file' | 'dir' | 'exe'; + content?: string; + children?: Record; +} + +export default function KernelPanic404() { + const outputRef = useRef(null); + const inputRef = useRef(null); + const inputContainerRef = useRef(null); + const [systemFrozen, setSystemFrozen] = useState(false); + const [currentMusic, setCurrentMusic] = useState<{ stop?: () => void } | null>(null); + const [hawkinsActive, setHawkinsActive] = useState(false); + const [fsocietyActive, setFsocietyActive] = useState(false); + const [commandHistory, setCommandHistory] = useState([]); + const [historyIndex, setHistoryIndex] = useState(-1); + const [currentPath, setCurrentPath] = useState(null); + const [pathStr, setPathStr] = useState("~"); + const audioCtxRef = useRef(null); + + // File system structure + const fileSystem: { home: FileSystemNode; var: FileSystemNode; etc: FileSystemNode; bin: FileSystemNode; tmp: FileSystemNode } = { + home: { + type: "dir", + children: { + guest: { + type: "dir", + children: { + "readme.txt": { + type: "file", + content: "ERROR 404: Page Not Found.\n\nSystem Integrity: 89%\nCheck /var/log for clues.\n\nTry: ls -la, cat .bash_history" + }, + ".bash_history": { + type: "file", + content: "ls -la\nwhoami\nfsociety\nexit" + }, + "todo.txt": { + type: "file", + content: "- Fix the internet\n- Calculate the Ultimate Answer (try: 42)\n- Buy milk\n- Check Hawkins Lab logs" + }, + "projects": { + type: "dir", + children: { + website: { + type: "dir", + children: { + "index.html": { type: "file", content: "404" } + } + } + } + } + } + } + } + }, + var: { + type: "dir", + children: { + log: { + type: "dir", + children: { + syslog: { + type: "file", + content: "[ERR] Reality breach detected in HAWKINS_LAB sector.\n[WARN] Subject 011 has escaped containment.\n[ALERT] Dimensional gate unstable.\n[INFO] Try command: hawkins or 011" + }, + "kern.log": { + type: "file", + content: "[ 0.000000] Linus Torvalds: 'This kernel is garbage.'\n[ 0.100000] Kernel tainted: M (Module has bad license)\n[ 0.200000] Torvalds: 'I'm not angry, just disappointed.'" + }, + "auth.log": { + type: "file", + content: "Failed password for root from 127.0.0.1\nFailed password for elliot from 127.0.0.1" + } + } + } + } + }, + etc: { + type: "dir", + children: { + passwd: { + type: "file", + content: "root:x:0:0:root:/root:/bin/bash\nguest:x:1000:1000:guest:/home/guest:/bin/bash\nelliot:x:509:509:mr_robot:/home/elliot:/bin/sh" + }, + hosts: { + type: "file", + content: "127.0.0.1 localhost\n127.0.0.1 e-corp.com\n0.0.0.0 reality" + } + } + }, + bin: { + type: "dir", + children: { + ls: { type: "exe" }, + cat: { type: "exe" }, + grep: { type: "exe" }, + find: { type: "exe" } + } + }, + tmp: { + type: "dir", + children: {} + } + }; + + const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); + + const printLine = (text: string, type?: string) => { + if (!outputRef.current) return; + const d = document.createElement('div'); + d.innerHTML = text; + if (type === 'log-warn') d.style.color = '#ffb000'; + if (type === 'log-err' || type === 'alert') d.style.color = '#ff3333'; + if (type === 'log-dim') d.style.opacity = '0.6'; + if (type === 'log-sys') d.style.color = 'cyan'; + if (type === 'log-k') d.style.color = '#fff'; + if (type === 'pulse-red') { + d.classList.add('pulse-red'); + d.style.color = '#ff3333'; + d.style.textShadow = '0 0 10px red'; + } + outputRef.current.appendChild(d); + if (outputRef.current) { + outputRef.current.scrollTop = outputRef.current.scrollHeight; + } + }; + + const playSynth = (type: string) => { + try { + if (!audioCtxRef.current || systemFrozen) return; + const t = audioCtxRef.current.currentTime; + const osc = audioCtxRef.current.createOscillator(); + const gain = audioCtxRef.current.createGain(); + osc.connect(gain); + gain.connect(audioCtxRef.current.destination); + + if (type === 'key') { + osc.type = 'square'; + osc.frequency.setValueAtTime(600, t); + gain.gain.setValueAtTime(0.02, t); + gain.gain.exponentialRampToValueAtTime(0.001, t + 0.05); + osc.start(); + osc.stop(t + 0.05); + } else if (type === 'beep') { + osc.type = 'sine'; + osc.frequency.setValueAtTime(800, t); + gain.gain.setValueAtTime(0.1, t); + gain.gain.exponentialRampToValueAtTime(0.001, t + 0.2); + osc.start(); + osc.stop(t + 0.2); + } + } catch { + // Ignore audio errors + } + }; + + const getCurrentDir = (): FileSystemNode => { + if (pathStr === "~" || pathStr.startsWith("~/")) { + return fileSystem.home.children!.guest; + } else if (pathStr.startsWith("/var/log")) { + // Return a wrapper node for /var/log directory + return { + type: 'dir', + children: fileSystem.var.children!.log.children + }; + } else if (pathStr.startsWith("/var")) { + return fileSystem.var; + } else if (pathStr.startsWith("/etc")) { + return fileSystem.etc; + } else if (pathStr.startsWith("/bin")) { + return fileSystem.bin; + } + return currentPath || fileSystem.home.children!.guest; + }; + + const runCmd = async (cmdRaw: string) => { + if (systemFrozen || !outputRef.current) return; + + printLine(`guest@404:${pathStr}$ ${cmdRaw}`, 'log-dim'); + const args = cmdRaw.split(/\s+/); + const cmd = args[0].toLowerCase(); + + const newHistory = [...commandHistory, cmdRaw]; + setCommandHistory(newHistory); + setHistoryIndex(newHistory.length); + + await sleep(100); + + const dir = getCurrentDir(); + + switch (cmd) { + case 'help': + printLine("--- SYSTEM UTILS ---", "log-sys"); + printLine(" ls, cd, cat, grep, find, pwd, clear"); + printLine(" whoami, uname, history, date, uptime"); + printLine(" head, tail, wc, sort, uniq"); + printLine("--- NETWORK ---", "log-sys"); + printLine(" ping, hostname"); + printLine("--- PROCESSES ---", "log-sys"); + printLine(" ps, top, kill"); + printLine("(Hints are hidden in the file system - try ls -la)"); + break; + + case 'ls': + const showHidden = args.includes('-a') || args.includes('-la') || args.includes('-l'); + const longFormat = args.includes('-l') || args.includes('-la'); + const items = Object.keys(dir.children || {}) + .filter(n => !n.startsWith('.') || showHidden); + if (showHidden) { + items.unshift('..'); + items.unshift('.'); + } + items.sort((a, b) => { + if (a === '.') return -1; + if (b === '.') return 1; + if (a === '..') return -1; + if (b === '..') return 1; + const itemA = dir.children?.[a] as FileSystemNode | undefined; + const itemB = dir.children?.[b] as FileSystemNode | undefined; + if (!itemA || !itemB) return 0; + if (itemA.type === 'dir' && itemB.type !== 'dir') return -1; + if (itemA.type !== 'dir' && itemB.type === 'dir') return 1; + return a.localeCompare(b); + }); + if (longFormat) { + printLine(`total ${items.length}`); + items.forEach(n => { + const item = dir.children?.[n]; + if (!item && n !== '.' && n !== '..') return; + const isDir = item?.type === 'dir' || n === '.' || n === '..'; + const perms = isDir ? 'drwxr-xr-x' : '-rw-r--r--'; + const links = isDir ? '2' : '1'; + const size = isDir ? '4096'.padStart(8) : (item?.content?.length || '0').toString().padStart(8); + const date = new Date(); + const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; + const month = monthNames[date.getMonth()]; + const day = date.getDate().toString().padStart(2); + const time = date.toTimeString().substring(0, 5); + const dateStr = `${month} ${day} ${time}`; + const filename = isDir ? `${n}/` : n; + printLine(`${perms} ${links} guest guest ${size} ${dateStr} ${filename}`); + }); + } else { + const formatted = items.map(n => { + const item = dir.children?.[n]; + if (n === '.' || n === '..') return `${n}/`; + if (item?.type === 'dir') return `${n}/`; + if (item?.type === 'exe') return `${n}*`; + return n; + }); + printLine(formatted.join(' ')); + } + break; + + case 'cat': + const file = dir.children?.[args[1]] as FileSystemNode | undefined; + if (file && file.type === 'file') { + printLine(file.content || ''); + } else { + printLine(`cat: ${args[1] || ''}: No such file`, 'log-err'); + } + break; + + case 'cd': + if (!args[1]) { + setCurrentPath(fileSystem.home.children!.guest); + setPathStr("~"); + } else if (args[1] === '..') { + if (pathStr === "/var/log") { + setCurrentPath(fileSystem.var); + setPathStr("/var"); + } else if (pathStr === "/var") { + setPathStr("/"); + } else { + setCurrentPath(fileSystem.home.children!.guest); + setPathStr("~"); + } + } else if (args[1] === '~' || args[1] === '/home/guest') { + setCurrentPath(fileSystem.home.children!.guest); + setPathStr("~"); + } else if (args[1].startsWith('/var/log')) { + setCurrentPath({ + type: 'dir', + children: fileSystem.var.children!.log.children + }); + setPathStr("/var/log"); + } else if (args[1].startsWith('/var')) { + setCurrentPath(fileSystem.var); + setPathStr("/var"); + } else if (args[1].startsWith('/etc')) { + setCurrentPath(fileSystem.etc); + setPathStr("/etc"); + } else { + const subdir = dir.children?.[args[1]] as FileSystemNode | undefined; + if (subdir && subdir.type === 'dir') { + setCurrentPath(subdir); + setPathStr(pathStr === "~" ? `~/${args[1]}` : `${pathStr}/${args[1]}`); + } else { + printLine(`cd: ${args[1]}: No such file or directory`, 'log-err'); + } + } + break; + + case 'pwd': + printLine(pathStr === "~" ? "/home/guest" : pathStr); + break; + + case 'grep': + if (args.length < 3) { + printLine("Usage: grep [pattern] [file]"); + } else { + const grepFile = dir.children?.[args[2]] as FileSystemNode | undefined; + if (grepFile && grepFile.type === 'file' && grepFile.content) { + const lines = grepFile.content.split('\n'); + lines.forEach(l => { + if (l.toLowerCase().includes(args[1].toLowerCase())) { + printLine(l); + } + }); + } else { + printLine(`grep: ${args[2]}: No such file`); + } + } + break; + + case 'whoami': + printLine("guest"); + break; + + case 'uname': + if (args.includes('-a')) { + printLine("Linux 404-void 4.0.4-void #1 SMP PREEMPT Fri Jan 09 2025 x86_64 GNU/Linux"); + } else { + printLine("Linux"); + } + break; + + case 'date': + printLine(new Date().toString()); + break; + + case 'uptime': + const uptime = Math.floor((Date.now() - performance.timing.navigationStart) / 1000); + const hours = Math.floor(uptime / 3600); + const mins = Math.floor((uptime % 3600) / 60); + const secs = uptime % 60; + printLine(`up ${hours}:${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}, 1 user, load average: 0.00, 0.00, 0.00`); + break; + + case 'clear': + if (outputRef.current) outputRef.current.innerHTML = ""; + break; + + case 'history': + commandHistory.forEach((c, i) => printLine(` ${i + 1} ${c}`)); + break; + + case 'exit': + window.location.href = '/'; + break; + + // Easter eggs + case 'hawkins': + case '011': + case 'eleven': + case 'upsidedown': + if (hawkinsActive) { + printLine("Closing dimensional gate...", 'log-warn'); + setHawkinsActive(false); + if (currentMusic) { + currentMusic.stop?.(); + setCurrentMusic(null); + } + document.body.classList.remove('hawkins'); + } else { + setHawkinsActive(true); + document.body.classList.add('hawkins'); + printLine("Entering the Upside Down...", 'log-err'); + } + break; + + case 'fsociety': + case 'elliot': + case 'bonsoir': + if (fsocietyActive) { + setFsocietyActive(false); + setSystemFrozen(false); + if (inputContainerRef.current) inputContainerRef.current.style.display = 'flex'; + if (currentMusic) { + currentMusic.stop?.(); + setCurrentMusic(null); + } + document.body.classList.remove('fsociety-boot'); + } else { + setFsocietyActive(true); + setSystemFrozen(true); + if (inputContainerRef.current) inputContainerRef.current.style.display = 'none'; + if (outputRef.current) outputRef.current.innerHTML = ""; + document.body.classList.add('fsociety-boot'); + printLine("$ ./fsociety.sh", 'log-k'); + await sleep(250); + printLine("[*] Initializing breach protocol...", 'log-warn'); + await sleep(500); + printLine("Hello friend.", 'log-k'); + await sleep(1000); + location.reload(); + } + break; + + case '42': + case 'answer': + printLine("Initializing Deep Thought...", 'log-sys'); + await sleep(600); + printLine("Deep Thought: The Answer to the Ultimate Question of Life, the Universe, and Everything is...", 'log-k'); + await sleep(1500); + printLine("42", 'log-k'); + break; + + case 'rm': + if (args[1] === '-rf' && args[2] === '/') { + setSystemFrozen(true); + if (inputContainerRef.current) inputContainerRef.current.style.display = 'none'; + printLine("CRITICAL: Attempting to delete root filesystem...", 'log-err'); + await sleep(500); + printLine("KERNEL PANIC: Unable to handle kernel paging request", 'pulse-red'); + await sleep(2000); + location.reload(); + } else if (args[1]) { + printLine("rm: cannot remove: Read-only file system", 'log-err'); + } else { + printLine("Usage: rm [file]"); + } + break; + + default: + printLine(`bash: ${cmd}: command not found`, 'log-err'); + } + + if (inputRef.current && !systemFrozen) { + setTimeout(() => inputRef.current?.focus(), 50); + } + }; + + useEffect(() => { + setCurrentPath(fileSystem.home.children!.guest); + + const initAudio = () => { + if (!audioCtxRef.current) { + try { + audioCtxRef.current = new (window.AudioContext || (window as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext)(); + } catch { + // Ignore + } + } + }; + + window.addEventListener('keydown', initAudio, { once: true }); + + const bootMessages = [ + { t: "[ 0.000000] Linux version 4.0.4-void (torvalds@kernel.org) (gcc version 9.4.0)", d: 200 }, + { t: "[ 0.050000] Command line: BOOT_IMAGE=/boot/vmlinuz-4.0.4 root=UUID=dead-beef ro quiet splash", d: 150 }, + { t: "[ 0.100000] x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers'", d: 100 }, + { t: "[ 0.150000] x86/fpu: Supporting XSAVE feature 0x002: 'SSE registers'", d: 100 }, + { t: "[ 0.200000] BIOS-provided physical RAM map:", d: 200 }, + { t: "[ 0.250000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable", d: 150 }, + { t: "[ 0.300000] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved", d: 150 }, + { t: "[ 0.400000] Memory: 64K/1048576K available (404K kernel code, 404K rwdata, 404K rodata)", d: 300 }, + { t: "[ 0.600000] Calibrating delay loop... 800.00 BogoMIPS (lpj=400000)", d: 200 }, + { t: "[ 0.800000] Security Framework initialized", d: 200 }, + { t: "[ 1.000000] Tainted kernel: M (Module has bad license) P (Proprietary module loaded)", type: 'log-warn', d: 400 }, + { t: "[ 1.200000] Linus Torvalds: 'I'm not angry, I'm just disappointed in this boot process.'", d: 600 }, + { t: "[ 1.500000] Torvalds: 'This code is garbage. Who wrote this?'", d: 500 }, + { t: "[ 2.000000] [ OK ] Started udev Kernel Device Manager.", d: 200 }, + { t: "[ 2.200000] [ OK ] Mounted /dev/sda1 (Root Filesystem).", d: 200 }, + { t: "[ 2.400000] [TIME] Timed out waiting for device /dev/reality.", type: 'log-warn', d: 600 }, + { t: "[ 2.800000] [DEPEND] Dependency failed for Local File Systems.", type: 'log-err', d: 300 }, + { t: "[ 3.000000] [FAILED] Failed to start The Internet.", type: 'log-err', d: 400 }, + { t: "[ 3.200000] [FAILED] Failed to start Meaning of Life service.", type: 'log-err', d: 400 }, + { t: "[ 3.500000] Welcome to emergency mode. Type 'help' for available commands.", d: 200 }, + ]; + + const runBoot = async () => { + for (const msg of bootMessages) { + printLine(msg.t, msg.type); + await sleep(msg.d); + } + if (inputContainerRef.current) { + inputContainerRef.current.style.display = 'flex'; + } + if (inputRef.current) { + setTimeout(() => inputRef.current?.focus(), 100); + } + }; + + if (outputRef.current) { + runBoot(); + } + + return () => { + if (currentMusic) { + currentMusic.stop?.(); + } + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return ( + <> +