š® UI pattern Ā· React state
Terminal Oracle
The complete CLI/chat interface skeleton ā the exact pattern behind every AI chat product, ready to wire to a real backend.
Use it for: AI chat products Ā· developer tools Ā· easter eggs
oracle@koah.ing
KOAH OS v17.85 ā the oracle is listening
type "help" to see what it knows
āÆ
The complete source
This is the exact file rendering the demo above ā a single self-contained React client component with its styles inline. Copy or download it, drop it into any React / Next.js project, and it runs. No extra dependencies.
oracle.jsx
1"use client";2import { useEffect, useRef, useState } from "react";34/* ============================================================5TERMINAL ORACLE ā a complete CLI-style interface pattern:6command parsing, history (ā/ā), typewriter output, and a7blinking caret. The skeleton for any "AI chat" or developer8tool aesthetic. Pure React state ā no terminal libraries.9============================================================ */1011const BANNER = [12"KOAH OS v17.85 ā the oracle is listening",13'type "help" to see what it knows',14];1516const RESPONSES = {17help: [18"available commands:",19" about ā who is Koah Ing?",20" magic ā receive one (1) act of digital magic",21" skills ā the 2026 web platform codex",22" clear ā wipe the slate",23],24about: [25"Koah Ing: teacher Ā· koach Ā· performer Ā· inventor.",26"Thinks in multiple dimensions. Makes your thING genius.",27],28magic: [29"š© watch closely...",30"...your card was the seven of stars. correct?",31"(the oracle is never wrong. occasionally early.)",32],33skills: [34"WebGPU (Baseline 2026) Ā· scroll-driven CSS Ā· view transitions",35"anchor positioning Ā· ::scroll-button carousels Ā· @property",36"all demonstrated, with source, in this very Lab.",37],38};3940export default function Oracle() {41const [lines, setLines] = useState(BANNER.map((t) => ({ t, who: "sys" })));42const [input, setInput] = useState("");43const [history, setHistory] = useState([]);44const [hIdx, setHIdx] = useState(-1);45const scroller = useRef(null);46const typing = useRef(false);4748// typewriter: reveal queued lines character by character49const typeOut = (queue) => {50typing.current = true;51let li = 0;52let ci = 0;53const tick = () => {54if (li >= queue.length) {55typing.current = false;56return;57}58ci++;59const partial = queue[li].slice(0, ci);60setLines((prev) => {61const next = [...prev];62if (next[next.length - 1]?.who === "oracle-typing") next.pop();63return [...next, { t: partial, who: ci >= queue[li].length ? "oracle" : "oracle-typing" }];64});65if (ci >= queue[li].length) {66li++;67ci = 0;68}69setTimeout(tick, 14);70};71tick();72};7374const run = (raw) => {75const cmd = raw.trim().toLowerCase();76if (!cmd) return;77setLines((p) => [...p, { t: `⯠${raw}`, who: "you" }]);78setHistory((h) => [raw, ...h]);79setHIdx(-1);80if (cmd === "clear") {81setTimeout(() => setLines([]), 120);82return;83}84const out = RESPONSES[cmd] || [85`unknown command: "${cmd}"`,86'the oracle suggests: "help"',87];88typeOut(out);89};9091const onKey = (e) => {92if (e.key === "Enter" && !typing.current) {93run(input);94setInput("");95} else if (e.key === "ArrowUp") {96e.preventDefault();97const ni = Math.min(hIdx + 1, history.length - 1);98if (history[ni]) {99setHIdx(ni);100setInput(history[ni]);101}102} else if (e.key === "ArrowDown") {103e.preventDefault();104const ni = hIdx - 1;105setHIdx(ni);106setInput(ni >= 0 ? history[ni] : "");107}108};109110useEffect(() => {111scroller.current?.scrollTo({ top: scroller.current.scrollHeight });112}, [lines]);113114return (115<div116className="rounded-3xl border border-white/15 overflow-hidden font-mono"117style={{ background: "#070710" }}118onClick={() => document.getElementById("oracle-input")?.focus()}119>120<div className="flex items-center gap-2 px-5 py-3 border-b border-white/10">121<span className="w-3 h-3 rounded-full bg-rose-500/80" />122<span className="w-3 h-3 rounded-full bg-amber-400/80" />123<span className="w-3 h-3 rounded-full bg-emerald-400/80" />124<span className="ml-3 text-[1.2rem] text-white/40">oracle@koah.ing</span>125</div>126<div ref={scroller} className="h-[44svh] overflow-y-auto px-5 py-4 text-[1.4rem] leading-relaxed">127{lines.map((l, i) => (128<p129key={i}130className={131l.who === "you"132? "text-cyan-300"133: l.who === "sys"134? "text-white/40"135: "text-emerald-300"136}137>138{l.t}139{l.who === "oracle-typing" && <span className="oracle-caret">ā</span>}140</p>141))}142</div>143<div className="flex items-center gap-3 px-5 py-4 border-t border-white/10">144<span className="text-violet-400 text-[1.4rem]">āÆ</span>145<input146id="oracle-input"147value={input}148onChange={(e) => setInput(e.target.value)}149onKeyDown={onKey}150placeholder='try "magic" ā ā for history'151className="flex-1 bg-transparent outline-none text-white text-[1.4rem] placeholder:text-white/25"152autoComplete="off"153spellCheck={false}154/>155</div>156<style>{`157.oracle-caret { animation: oracle-blink 1s steps(1) infinite; }158@keyframes oracle-blink { 50% { opacity: 0; } }159`}</style>160</div>161);162}163