/**
* CatOS v9.0 (Whiskers Edition) đąâđģ
* A pseudo desktop operating system portfolio
*/
// CatOS Core System
const CatOS = {
// System state
windows: new Map(),
apps: new Map(),
nextWindowId: 1,
focusedWindow: null,
startMenuOpen: false,
// Project data
projects: {
'sneaky-cat-proxy': {
title: 'Sneaky Cat Proxy',
icon: 'đ',
description: 'A purr-fessional proxy that helps cats navigate the internet stealthily! đĩī¸ââī¸',
technologies: ['Node.js', 'Express', 'Stealth'],
features: [
'Stealth browsing capabilities',
'Cat-safe internet filtering',
'Automatic mouse toy detection',
'Built-in treat dispenser API'
],
github: 'https://github.com/catcoder/sneaky-proxy',
demo: 'https://sneaky-cat-proxy.vercel.app'
},
'cat-photo-gallery': {
title: 'Cat Photo Gallery',
icon: 'đ¸',
description: 'A claw-some gallery to showcase all your favorite cat pics with purr-fect filtering! đģ',
technologies: ['React', 'TypeScript', 'Tailwind'],
features: [
'Advanced cat photo filtering',
'Automatic whisker detection',
'Paw print watermarking',
'Social sharing for cat influencers'
],
github: 'https://github.com/catcoder/cat-gallery',
demo: 'https://cat-gallery.vercel.app'
},
'robo-cat-manager': {
title: 'Robo-Cat Manager',
icon: 'đ¤',
description: 'Managing Discord bots like herding cats! Keep your digital kitties in line with style! đąâđģ',
technologies: ['Discord.js', 'MongoDB', 'Docker'],
features: [
'Multi-bot management dashboard',
'Automatic yarn ball deployment',
'Cat behavior analytics',
'Emergency tuna button'
],
github: 'https://github.com/catcoder/robo-cat-manager',
demo: 'https://discord-bot-manager.vercel.app'
}
},
// Initialize CatOS
init() {
this.showLoadingScreen();
this.setupEventListeners();
this.updateClock();
this.registerApps();
this.setRandomWallpaper();
// Boot sequence
setTimeout(() => {
this.hideLoadingScreen();
this.playStartupSound();
this.showWelcomeMessage();
}, 3000);
},
// Event Listeners
setupEventListeners() {
// Desktop icon interactions
document.querySelectorAll('.desktop-icon').forEach(icon => {
icon.addEventListener('dblclick', this.handleIconDoubleClick.bind(this));
icon.addEventListener('click', this.handleIconClick.bind(this));
});
// Start button
document.getElementById('start-button').addEventListener('click', this.toggleStartMenu.bind(this));
// Start menu apps
document.querySelectorAll('.menu-app').forEach(app => {
app.addEventListener('click', this.handleMenuAppClick.bind(this));
});
// Desktop context menu
document.getElementById('desktop').addEventListener('contextmenu', this.showContextMenu.bind(this));
// Close context menu on click
document.addEventListener('click', this.hideContextMenu.bind(this));
// Close start menu on outside click
document.addEventListener('click', (e) => {
if (!e.target.closest('.start-button') && !e.target.closest('.start-menu')) {
this.hideStartMenu();
}
});
// Keyboard shortcuts
document.addEventListener('keydown', this.handleKeyboard.bind(this));
// Window container clicks (deselect icons)
document.getElementById('windows-container').addEventListener('click', (e) => {
if (e.target.id === 'windows-container') {
this.deselectAllIcons();
}
});
},
// Icon interactions
handleIconClick(e) {
this.deselectAllIcons();
e.currentTarget.classList.add('selected');
},
handleIconDoubleClick(e) {
const icon = e.currentTarget;
const appType = icon.dataset.app;
const projectId = icon.dataset.project;
if (appType === 'project-viewer' && projectId) {
this.launchApp('project-viewer', { projectId });
} else {
this.launchApp(appType);
}
},
deselectAllIcons() {
document.querySelectorAll('.desktop-icon.selected').forEach(icon => {
icon.classList.remove('selected');
});
},
// Start Menu
toggleStartMenu() {
const menu = document.getElementById('start-menu');
const button = document.getElementById('start-button');
if (this.startMenuOpen) {
this.hideStartMenu();
} else {
menu.classList.add('show');
button.classList.add('active');
this.startMenuOpen = true;
}
},
hideStartMenu() {
const menu = document.getElementById('start-menu');
const button = document.getElementById('start-button');
menu.classList.remove('show');
button.classList.remove('active');
this.startMenuOpen = false;
},
handleMenuAppClick(e) {
const appType = e.currentTarget.dataset.app;
this.launchApp(appType);
this.hideStartMenu();
},
// Context Menu
showContextMenu(e) {
e.preventDefault();
const menu = document.getElementById('context-menu');
menu.style.left = e.clientX + 'px';
menu.style.top = e.clientY + 'px';
menu.classList.add('show');
},
hideContextMenu() {
document.getElementById('context-menu').classList.remove('show');
},
// App Management
registerApps() {
this.apps.set('terminal', {
title: 'Terminal',
icon: 'đģ',
create: () => this.createTerminalApp()
});
this.apps.set('project-viewer', {
title: 'Project Viewer',
icon: 'đ',
create: (options) => this.createProjectViewerApp(options)
});
this.apps.set('about', {
title: 'About CatOS',
icon: 'đ',
create: () => this.createAboutApp()
});
this.apps.set('contact', {
title: 'Contact',
icon: 'đ§',
create: () => this.createContactApp()
});
this.apps.set('file-explorer', {
title: 'File Explorer',
icon: 'đ',
create: () => this.createFileExplorerApp()
});
},
launchApp(appType, options = {}) {
const app = this.apps.get(appType);
if (!app) {
this.showNotification(`App '${appType}' not found! đ`, 'error');
return;
}
// Check if app is already running (except project-viewer which can have multiple instances)
if (appType !== 'project-viewer') {
for (const [windowId, window] of this.windows) {
if (window.appType === appType) {
this.focusWindow(windowId);
return;
}
}
}
const content = app.create(options);
const windowId = this.createWindow({
title: app.title,
icon: app.icon,
content: content,
appType: appType
});
this.addToTaskbar(windowId, app);
},
// Window Management
createWindow(options) {
const windowId = `window-${this.nextWindowId++}`;
const window = document.createElement('div');
window.className = 'window focused';
window.id = windowId;
window.innerHTML = `
${options.icon}
${options.title}
${options.content}
`;
// Position window
const offset = (this.nextWindowId - 2) * 30;
window.style.left = (100 + offset) + 'px';
window.style.top = (50 + offset) + 'px';
window.style.width = options.width || '600px';
window.style.height = options.height || '400px';
// Add to container
document.getElementById('windows-container').appendChild(window);
// Store window data
this.windows.set(windowId, {
element: window,
title: options.title,
icon: options.icon,
appType: options.appType,
minimized: false,
maximized: false
});
// Setup window events
this.setupWindowEvents(windowId);
this.focusWindow(windowId);
return windowId;
},
setupWindowEvents(windowId) {
const window = this.windows.get(windowId);
const element = window.element;
// Window controls
element.querySelectorAll('.window-control').forEach(btn => {
btn.addEventListener('click', (e) => {
e.stopPropagation();
const action = btn.dataset.action;
switch(action) {
case 'minimize':
this.minimizeWindow(windowId);
break;
case 'maximize':
this.toggleMaximizeWindow(windowId);
break;
case 'close':
this.closeWindow(windowId);
break;
}
});
});
// Window focus
element.addEventListener('mousedown', () => {
this.focusWindow(windowId);
});
// Window dragging
const titlebar = element.querySelector('.window-titlebar');
this.makeDraggable(element, titlebar);
// Window resizing
this.setupWindowResizing(windowId);
},
focusWindow(windowId) {
// Unfocus all windows
document.querySelectorAll('.window').forEach(w => {
w.classList.remove('focused');
});
// Update taskbar
document.querySelectorAll('.taskbar-app').forEach(app => {
app.classList.remove('focused');
});
// Focus target window
const window = this.windows.get(windowId);
if (window) {
window.element.classList.add('focused');
this.focusedWindow = windowId;
// Update taskbar
const taskbarApp = document.querySelector(`[data-window-id="${windowId}"]`);
if (taskbarApp) {
taskbarApp.classList.add('focused');
}
}
},
minimizeWindow(windowId) {
const window = this.windows.get(windowId);
if (window) {
window.element.classList.add('minimized');
window.minimized = true;
// Update taskbar
const taskbarApp = document.querySelector(`[data-window-id="${windowId}"]`);
if (taskbarApp) {
taskbarApp.classList.remove('focused');
}
}
},
toggleMaximizeWindow(windowId) {
const window = this.windows.get(windowId);
if (window) {
if (window.maximized) {
window.element.classList.remove('maximized');
window.maximized = false;
} else {
window.element.classList.add('maximized');
window.maximized = true;
}
}
},
closeWindow(windowId) {
const window = this.windows.get(windowId);
if (window) {
// Remove from DOM
window.element.remove();
// Remove from taskbar
const taskbarApp = document.querySelector(`[data-window-id="${windowId}"]`);
if (taskbarApp) {
taskbarApp.remove();
}
// Remove from windows map
this.windows.delete(windowId);
// Focus another window if this was focused
if (this.focusedWindow === windowId) {
const remainingWindows = Array.from(this.windows.keys());
if (remainingWindows.length > 0) {
this.focusWindow(remainingWindows[remainingWindows.length - 1]);
} else {
this.focusedWindow = null;
}
}
}
},
// Taskbar Management
addToTaskbar(windowId, app) {
const taskbar = document.getElementById('taskbar-apps');
const taskbarApp = document.createElement('div');
taskbarApp.className = 'taskbar-app focused';
taskbarApp.dataset.windowId = windowId;
taskbarApp.innerHTML = `
${app.icon}
${app.title}
`;
taskbarApp.addEventListener('click', () => {
const window = this.windows.get(windowId);
if (window) {
if (window.minimized) {
window.element.classList.remove('minimized');
window.minimized = false;
}
this.focusWindow(windowId);
}
});
taskbar.appendChild(taskbarApp);
},
// Dragging functionality
makeDraggable(element, handle) {
let isDragging = false;
let currentX, currentY, initialX, initialY, xOffset = 0, yOffset = 0;
const dragStart = (e) => {
const window = this.windows.get(element.id);
if (window && window.maximized) return; // Can't drag maximized windows
if (e.type === "touchstart") {
initialX = e.touches[0].clientX - xOffset;
initialY = e.touches[0].clientY - yOffset;
} else {
initialX = e.clientX - xOffset;
initialY = e.clientY - yOffset;
}
if (e.target === handle || handle.contains(e.target)) {
isDragging = true;
document.body.classList.add('dragging');
}
};
const drag = (e) => {
if (isDragging) {
e.preventDefault();
if (e.type === "touchmove") {
currentX = e.touches[0].clientX - initialX;
currentY = e.touches[0].clientY - initialY;
} else {
currentX = e.clientX - initialX;
currentY = e.clientY - initialY;
}
xOffset = currentX;
yOffset = currentY;
element.style.left = currentX + "px";
element.style.top = currentY + "px";
}
};
const dragEnd = () => {
initialX = currentX;
initialY = currentY;
isDragging = false;
document.body.classList.remove('dragging');
};
handle.addEventListener("mousedown", dragStart);
handle.addEventListener("touchstart", dragStart);
document.addEventListener("mousemove", drag);
document.addEventListener("touchmove", drag);
document.addEventListener("mouseup", dragEnd);
document.addEventListener("touchend", dragEnd);
},
// Window resizing functionality
setupWindowResizing(windowId) {
const window = this.windows.get(windowId);
const element = window.element;
const resizeHandles = element.querySelectorAll('.window-resize-handle');
let isResizing = false;
let resizeDirection = '';
let startX, startY, startWidth, startHeight, startLeft, startTop;
const resizeStart = (e) => {
const windowData = this.windows.get(element.id);
if (windowData && windowData.maximized) return; // Can't resize maximized windows
e.preventDefault();
e.stopPropagation();
isResizing = true;
resizeDirection = e.target.dataset.direction;
startX = e.clientX;
startY = e.clientY;
startWidth = parseInt(getComputedStyle(element).width, 10);
startHeight = parseInt(getComputedStyle(element).height, 10);
startLeft = parseInt(getComputedStyle(element).left, 10);
startTop = parseInt(getComputedStyle(element).top, 10);
element.classList.add('resizing');
document.body.style.cursor = e.target.style.cursor;
document.body.style.userSelect = 'none';
};
const resize = (e) => {
if (!isResizing) return;
e.preventDefault();
const deltaX = e.clientX - startX;
const deltaY = e.clientY - startY;
let newWidth = startWidth;
let newHeight = startHeight;
let newLeft = startLeft;
let newTop = startTop;
// Calculate new dimensions based on resize direction
if (resizeDirection.includes('e')) {
newWidth = Math.max(300, startWidth + deltaX);
}
if (resizeDirection.includes('w')) {
newWidth = Math.max(300, startWidth - deltaX);
newLeft = startLeft + (startWidth - newWidth);
}
if (resizeDirection.includes('s')) {
newHeight = Math.max(200, startHeight + deltaY);
}
if (resizeDirection.includes('n')) {
newHeight = Math.max(200, startHeight - deltaY);
newTop = startTop + (startHeight - newHeight);
}
// Apply new dimensions
element.style.width = newWidth + 'px';
element.style.height = newHeight + 'px';
element.style.left = newLeft + 'px';
element.style.top = newTop + 'px';
};
const resizeEnd = () => {
if (!isResizing) return;
isResizing = false;
resizeDirection = '';
element.classList.remove('resizing');
document.body.style.cursor = '';
document.body.style.userSelect = '';
};
// Add event listeners to all resize handles
resizeHandles.forEach(handle => {
handle.addEventListener('mousedown', resizeStart);
});
document.addEventListener('mousemove', resize);
document.addEventListener('mouseup', resizeEnd);
},
// App Creation Functions
createTerminalApp() {
const terminalId = `terminal-${Date.now()}`;
setTimeout(() => {
this.initializeTerminal(terminalId);
}, 100);
return `
cat@catos:~$
Welcome to CatOS Terminal! đą
cat@catos:~$
Type 'help' for available commands or 'meow' for cat wisdom
cat@catos:~$
`;
},
createProjectViewerApp(options) {
const project = this.projects[options.projectId];
if (!project) {
return 'Project not found! đ
';
}
return `
đ ī¸ Technologies
${project.technologies.map(tech => `${tech}`).join('')}
⨠Features
${project.features.map(feature => `- ${feature}
`).join('')}
`;
},
createAboutApp() {
return `
System Information
Developer:
Rafael (Certified Cat Whisperer)
Uptime:
5+ years coding experience
Memory:
â GB coffee-powered RAM
Storage:
â TB of cat photos and code
`;
},
createContactApp() {
return `
`;
},
createFileExplorerApp() {
return `
`;
},
// System functions
updateClock() {
const clockElement = document.querySelector('.time');
const updateTime = () => {
const now = new Date();
const time = now.toLocaleTimeString([], {
hour: '2-digit',
minute: '2-digit',
hour12: true
});
clockElement.textContent = time;
};
updateTime();
setInterval(updateTime, 1000);
},
showLoadingScreen() {
const messages = [
'Initializing cat-ware...',
'Loading whiskers.dll...',
'Calibrating purr engine...',
'Installing 9 lives protection...',
'Warming up the litter box...',
'Ready to pounce! đž'
];
let messageIndex = 0;
const messageElement = document.querySelector('.loading-message');
const updateMessage = () => {
if (messageIndex < messages.length) {
messageElement.textContent = messages[messageIndex];
messageIndex++;
setTimeout(updateMessage, 500);
}
};
updateMessage();
},
hideLoadingScreen() {
const loadingScreen = document.getElementById('loading-screen');
loadingScreen.classList.add('hidden');
},
playStartupSound() {
// Soft meow sound would go here
console.log('đą *gentle startup meow*');
},
showWelcomeMessage() {
this.showNotification('Welcome to CatOS! Double-click icons to launch apps đž', 'success');
},
showNotification(message, type = 'info') {
const notification = document.createElement('div');
notification.className = `notification ${type}`;
notification.innerHTML = `
${type === 'success' ? 'â
' : type === 'error' ? 'â' : 'âšī¸'}
${message}
`;
// Add styles
Object.assign(notification.style, {
position: 'fixed',
top: '20px',
right: '20px',
background: type === 'error' ? '#fee2e2' : type === 'success' ? '#d1fae5' : '#dbeafe',
color: type === 'error' ? '#dc2626' : type === 'success' ? '#059669' : '#1d4ed8',
padding: '12px 16px',
borderRadius: '8px',
border: `1px solid ${type === 'error' ? '#fecaca' : type === 'success' ? '#a7f3d0' : '#bfdbfe'}`,
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
zIndex: '10000',
fontSize: '0.875rem',
maxWidth: '300px',
animation: 'slideIn 0.3s ease'
});
document.body.appendChild(notification);
// Auto remove after 3 seconds
setTimeout(() => {
notification.style.animation = 'slideOut 0.3s ease';
setTimeout(() => {
document.body.removeChild(notification);
}, 300);
}, 3000);
},
// Keyboard shortcuts
handleKeyboard(e) {
// Alt + Tab - Switch windows
if (e.altKey && e.key === 'Tab') {
e.preventDefault();
this.switchToNextWindow();
}
// Ctrl + Alt + T - Open terminal
if (e.ctrlKey && e.altKey && e.key.toLowerCase() === 't') {
e.preventDefault();
this.launchApp('terminal');
}
// Escape - Close context menu / start menu
if (e.key === 'Escape') {
this.hideContextMenu();
this.hideStartMenu();
}
},
switchToNextWindow() {
const windowIds = Array.from(this.windows.keys()).filter(id => {
const window = this.windows.get(id);
return !window.minimized;
});
if (windowIds.length === 0) return;
const currentIndex = windowIds.indexOf(this.focusedWindow);
const nextIndex = (currentIndex + 1) % windowIds.length;
this.focusWindow(windowIds[nextIndex]);
},
// Random Wallpaper System
setRandomWallpaper() {
const wallpaperCount = 6; // Update this if you add more wallpapers
const randomWallpaper = Math.floor(Math.random() * wallpaperCount) + 1;
const wallpaperPath = `./static/wallpapers/wallpaper${randomWallpaper}.png`;
// Set the wallpaper as the first background image
const desktop = document.getElementById('desktop');
const currentStyle = getComputedStyle(desktop);
const patternImage = `url('data:image/svg+xml,')`;
desktop.style.backgroundImage = `url('${wallpaperPath}'), ${patternImage}`;
// Log which wallpaper was selected (for debugging)
console.log(`đŧī¸ Selected wallpaper: wallpaper${randomWallpaper}.png`);
// Add a subtle fade-in effect
desktop.style.opacity = '0';
setTimeout(() => {
desktop.style.transition = 'opacity 0.5s ease';
desktop.style.opacity = '1';
}, 100);
},
// Terminal System
initializeTerminal(terminalId) {
const input = document.getElementById(`terminal-input-${terminalId}`);
const content = document.getElementById(`terminal-content-${terminalId}`);
const prompt = document.getElementById(`prompt-${terminalId}`);
if (!input || !content || !prompt) return;
// Terminal state
const terminal = {
currentDirectory: '/home/catcoder',
commandHistory: [],
historyIndex: -1,
visitorInfo: this.getVisitorInfo()
};
// Handle command input
input.addEventListener('keydown', (e) => {
if (e.key === 'Enter') {
const command = input.value.trim();
if (command) {
this.executeCommand(command, terminal, content, prompt);
terminal.commandHistory.push(command);
terminal.historyIndex = terminal.commandHistory.length;
}
input.value = '';
} else if (e.key === 'ArrowUp') {
e.preventDefault();
if (terminal.historyIndex > 0) {
terminal.historyIndex--;
input.value = terminal.commandHistory[terminal.historyIndex];
}
} else if (e.key === 'ArrowDown') {
e.preventDefault();
if (terminal.historyIndex < terminal.commandHistory.length - 1) {
terminal.historyIndex++;
input.value = terminal.commandHistory[terminal.historyIndex];
} else {
terminal.historyIndex = terminal.commandHistory.length;
input.value = '';
}
}
});
// Keep input focused
content.addEventListener('click', () => {
input.focus();
});
},
getVisitorInfo() {
return {
browser: navigator.userAgent.split(' ').pop().split('/')[0] || 'Unknown',
platform: navigator.platform || 'Unknown',
language: navigator.language || 'en-US',
screenWidth: screen.width,
screenHeight: screen.height,
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone || 'Unknown',
connection: navigator.connection?.effectiveType || 'Unknown',
visitTime: new Date().toISOString()
};
},
executeCommand(command, terminal, content, prompt) {
// Add command to terminal
this.addTerminalLine(content, `${prompt.textContent} ${command}`);
const [cmd, ...args] = command.toLowerCase().split(' ');
const fullArgs = args.join(' ');
// Command routing
switch(cmd) {
case 'help':
this.terminalHelp(content);
break;
case 'clear':
this.terminalClear(content);
break;
case 'whoami':
this.terminalWhoami(content, terminal.visitorInfo);
break;
case 'ls':
this.terminalLs(content, terminal.currentDirectory, fullArgs);
break;
case 'cat':
this.terminalCat(content, fullArgs, terminal.currentDirectory);
break;
case 'cd':
this.terminalCd(content, terminal, fullArgs);
break;
case 'pwd':
this.terminalPwd(content, terminal.currentDirectory);
break;
case 'ps':
this.terminalPs(content, fullArgs);
break;
case 'date':
this.terminalDate(content);
break;
case 'uptime':
this.terminalUptime(content);
break;
case 'meow':
this.terminalMeow(content, fullArgs);
break;
case 'purr':
this.terminalPurr(content);
break;
case 'whiskers':
this.terminalWhiskers(content);
break;
case 'nap':
this.terminalNap(content);
break;
case 'fortune':
this.terminalFortune(content);
break;
case 'curl':
this.terminalCurl(content, fullArgs);
break;
case 'git':
this.terminalGit(content, fullArgs);
break;
case 'npm':
this.terminalNpm(content, fullArgs);
break;
case 'history':
this.terminalHistory(content, terminal.commandHistory);
break;
case 'echo':
this.terminalEcho(content, fullArgs);
break;
default:
this.terminalUnknown(content, cmd);
}
// Update prompt based on directory
this.updatePrompt(prompt, terminal.currentDirectory);
// Scroll to bottom
content.scrollTop = content.scrollHeight;
},
addTerminalLine(content, text, className = 'terminal-text') {
const line = document.createElement('div');
line.className = 'terminal-line';
line.innerHTML = `${text}`;
content.appendChild(line);
},
addTerminalOutput(content, text) {
const line = document.createElement('div');
line.className = 'terminal-line';
line.innerHTML = `${text}`;
content.appendChild(line);
},
updatePrompt(prompt, currentDirectory) {
const dirName = currentDirectory.split('/').pop() || currentDirectory;
const shortDir = dirName === 'catcoder' ? '~' : dirName;
prompt.textContent = `cat@catos:${shortDir}$`;
},
// Terminal Commands
terminalHelp(content) {
const helpText = `
Available Commands:
đ Navigation:
ls [path] - List directory contents
cd [directory] - Change directory
pwd - Print working directory
cat [file] - Display file contents
đ System:
whoami - Display visitor information
ps aux - Show running processes
date - Show current date/time
uptime - Show system uptime
history - Show command history
clear - Clear terminal
đ Network:
curl [url] - Fetch web content
git [command] - Git operations
npm [command] - NPM operations
đą Cat Commands:
meow [message] - Cat responses
purr - Show happiness level
whiskers - ASCII cat art
nap - Activate screensaver
fortune - Cat wisdom
đĄ Tips:
Use â/â arrows for command history
Try: cat projects/sneaky-cat-proxy.md
`;
this.addTerminalOutput(content, helpText);
},
terminalClear(content) {
content.innerHTML = '';
},
terminalWhoami(content, visitorInfo) {
const info = `
đĩī¸ Visitor Detective Results:
âââââââââââââââââââââââââââââââââââââââ
â Browser: ${visitorInfo.browser}
â Platform: ${visitorInfo.platform}
â Screen: ${visitorInfo.screenWidth}x${visitorInfo.screenHeight}
â Language: ${visitorInfo.language}
â Timezone: ${visitorInfo.timezone}
â Connection: ${visitorInfo.connection}
â Visit Time: ${new Date(visitorInfo.visitTime).toLocaleString()}
âââââââââââââââââââââââââââââââââââââââ
*purrs* Nice to meet you, fellow human! đą
`;
this.addTerminalOutput(content, info);
},
terminalLs(content, currentDirectory, args) {
const directories = {
'/home/catcoder': [
{ name: 'Desktop', type: 'dir', icon: 'đ' },
{ name: 'projects', type: 'dir', icon: 'đ' },
{ name: 'documents', type: 'dir', icon: 'đ' },
{ name: 'pictures', type: 'dir', icon: 'đ' },
{ name: 'resume.pdf', type: 'file', icon: 'đ' },
{ name: 'cat-wisdom.txt', type: 'file', icon: 'đą' }
],
'/home/catcoder/projects': [
{ name: 'sneaky-cat-proxy', type: 'dir', icon: 'đ' },
{ name: 'cat-photo-gallery', type: 'dir', icon: 'đ¸' },
{ name: 'robo-cat-manager', type: 'dir', icon: 'đ¤' }
],
'/home/catcoder/documents': [
{ name: 'ideas.md', type: 'file', icon: 'đĄ' },
{ name: 'todo.txt', type: 'file', icon: 'đ' },
{ name: 'cat-facts.json', type: 'file', icon: 'đž' }
],
'/home/catcoder/pictures': [
{ name: 'profile-cat.jpg', type: 'file', icon: 'đ¸' },
{ name: 'project-screenshots', type: 'dir', icon: 'đ' },
{ name: 'memes', type: 'dir', icon: 'đš' }
]
};
const contents = directories[currentDirectory] || [];
if (contents.length === 0) {
this.addTerminalOutput(content, 'Directory is empty... like a cat\'s food bowl at 3am đŊī¸');
return;
}
let output = `đ Contents of ${currentDirectory}:\n`;
contents.forEach(item => {
const type = item.type === 'dir' ? 'DIR' : 'FILE';
output += `${item.icon} ${type} ${item.name}\n`;
});
this.addTerminalOutput(content, output);
},
terminalCat(content, filename, currentDirectory) {
const files = {
'resume.pdf': 'đ PDF files need special cat vision! Try opening the About app instead đ¸',
'cat-wisdom.txt': `đą Cat Wisdom Collection:
âĸ The early cat gets the tuna
âĸ In cat we trust, all others bring treats
âĸ Curiosity didn't kill the cat, it made it a developer
âĸ A cat's work is never done... mostly because we nap too much
âĸ Debugging is like herding cats, but the cats are invisible`,
'ideas.md': `đĄ Project Ideas:
- Cat-themed password manager
- Automatic laser pointer for remote work breaks
- AI that detects when treats are needed
- Social network for cats (MeowSpace)
- Smart litter box with analytics dashboard`,
'sneaky-cat-proxy.md': this.getProjectFile('sneaky-cat-proxy'),
'cat-photo-gallery.md': this.getProjectFile('cat-photo-gallery'),
'robo-cat-manager.md': this.getProjectFile('robo-cat-manager')
};
// Handle project files
if (filename.includes('/')) {
const parts = filename.split('/');
const projectName = parts[parts.length - 2];
if (this.projects[projectName]) {
this.addTerminalOutput(content, this.getProjectFile(projectName));
return;
}
}
const fileContent = files[filename];
if (fileContent) {
this.addTerminalOutput(content, fileContent);
} else {
this.addTerminalOutput(content, `cat: ${filename}: No such file or directory đ\nTry 'ls' to see available files!`);
}
},
getProjectFile(projectId) {
const project = this.projects[projectId];
if (!project) return 'Project not found! đ';
return `
${project.icon} ${project.title}
ââââââââââââââââââââââââââââââââââââââââââââââââââââ
Description:
${project.description}
Technologies:
${project.technologies.map(tech => `âĸ ${tech}`).join('\n')}
Features:
${project.features.map(feature => `đž ${feature}`).join('\n')}
Links:
âĸ GitHub: ${project.github}
âĸ Demo: ${project.demo}
*purrs approvingly* đ¸
`;
},
terminalCd(content, terminal, directory) {
if (!directory) {
terminal.currentDirectory = '/home/catcoder';
this.addTerminalOutput(content, 'Changed to home directory đ ');
return;
}
const validDirs = {
'~': '/home/catcoder',
'home': '/home/catcoder',
'projects': '/home/catcoder/projects',
'documents': '/home/catcoder/documents',
'pictures': '/home/catcoder/pictures',
'desktop': '/home/catcoder/Desktop',
'..': '/home/catcoder'
};
if (validDirs[directory]) {
terminal.currentDirectory = validDirs[directory];
this.addTerminalOutput(content, `Changed to ${terminal.currentDirectory} đ`);
} else {
this.addTerminalOutput(content, `cd: ${directory}: No such directory đ`);
}
},
terminalPwd(content, currentDirectory) {
this.addTerminalOutput(content, currentDirectory);
},
terminalPs(content, args) {
const processes = `
đ CatOS Process Status:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
cat 1337 15.2 8.5 245760 32156 pts/0 Sl+ 09:30 0:42 /usr/bin/coffee-maker
cat 2048 25.1 12.3 512000 45678 pts/1 R+ 09:31 1:23 /bin/cat-nap-scheduler
cat 4096 5.8 3.2 128000 12345 pts/2 S 09:32 0:15 /usr/bin/treat-dispenser
cat 8192 45.7 25.1 1024000 98765 pts/3 R+ 09:33 2:34 /opt/purr-engine --turbo
cat 1024 2.1 1.8 64000 5432 pts/4 S 09:34 0:08 /bin/whiskers-daemon
rafael 9999 98.5 75.2 2048000 234567 pts/5 R+ 09:35 5:67 /usr/bin/coding-furiously
Current mood: Caffeinated and ready to code! â
`;
this.addTerminalOutput(content, processes);
},
terminalDate(content) {
const now = new Date();
const catTime = `${now.toLocaleDateString()} ${now.toLocaleTimeString()}`;
this.addTerminalOutput(content, `${catTime} (Cat Standard Time) đąâ°`);
},
terminalUptime(content) {
const uptime = `
âąī¸ System Uptime:
Developer: 5+ years of coding experience
Coffee Machine: 3 hours since last refill â
Cat Nap Counter: 42 naps today đ´
Bug Squashing: 99.9% success rate đ
Treat Dispenser: Fully operational đ
Purr Engine: Running at optimal frequency đ¸
Load average: 1.33, 7.77, 42.00 (that's normal for a cat) đ
`;
this.addTerminalOutput(content, uptime);
},
terminalMeow(content, message) {
const responses = [
'đą *meows back softly*',
'đ¸ Purrfect! I understand completely!',
'đž *headbutts your screen affectionately*',
'đģ That\'s exactly what I was thinking!',
'đ You speak fluent cat!',
'đē *slow blinks* - that means "I love you" in cat',
'đąâđģ Meow back! Want to see my latest code?'
];
if (message) {
this.addTerminalOutput(content, `đą You said: "${message}"`);
this.addTerminalOutput(content, `đž Translation: "Please give me treats"`);
}
const response = responses[Math.floor(Math.random() * responses.length)];
this.addTerminalOutput(content, response);
},
terminalPurr(content) {
this.addTerminalOutput(content, `
đą *PURRRRRRRRRRRRRRRR*
đ¸ Happiness Level: 95% (needs more treats)
đž Satisfaction with website: MAXIMUM
đģ Current mood: Content developer cat`);
},
terminalWhiskers(content) {
const catArt = `
/\\_/\\
( o.o )
> ^ <
/\\_/\\ (
( ^.^ ) _) <- This is me coding
o_(")(")
|\\---/|
| o_o | <- Me when code works
\\_^_/
/\\_____/\\
/ o o \\ <- Me reviewing code
( == ^ == )
) (
( )
( ( ) ( ) )
(__(__)___(__)__)
`;
this.addTerminalOutput(content, catArt);
},
terminalNap(content) {
this.addTerminalOutput(content, 'đ´ Activating cat nap mode...');
setTimeout(() => {
this.addTerminalOutput(content, 'đą *stretches and yawns*');
setTimeout(() => {
this.addTerminalOutput(content, 'đ¸ Refreshed and ready to code! *tail swish*');
}, 2000);
}, 2000);
},
terminalFortune(content) {
const fortunes = [
'đą A cat\'s code is worth a thousand barks.',
'đ¸ Today is a good day to push to production.',
'đž Your code will run purrfectly... eventually.',
'đģ The best debugging happens at 2 AM with a cat on your keyboard.',
'đ Error 404: Treats not found. Please refill immediately.',
'đē In the future, all websites will be operated by cats.',
'đąâđģ Curiosity didn\'t kill the cat; it made it a senior developer.',
'đš Your next commit will be legendary... like a cat video.',
'đž Remember: There are no mistakes, only happy little bugs.',
'đą The cloud is just other people\'s litter boxes.'
];
const fortune = fortunes[Math.floor(Math.random() * fortunes.length)];
this.addTerminalOutput(content, `đŽ Cat Fortune:\n${fortune}`);
},
terminalCurl(content, url) {
if (!url) {
this.addTerminalOutput(content, 'curl: no URL specified đ\nUsage: curl ');
return;
}
this.addTerminalOutput(content, `đ Fetching ${url}...`);
setTimeout(() => {
if (url.includes('cat') || url.includes('meow')) {
this.addTerminalOutput(content, `đ¸ Connection successful! Cat-approved website detected.`);
} else if (url.includes('dog')) {
this.addTerminalOutput(content, `đ Warning: Canine content detected. Proceed with caution.`);
} else {
this.addTerminalOutput(content, `đĄ HTTP/1.1 200 OK - Site looks paw-some!`);
}
}, 1500);
},
terminalGit(content, args) {
if (args.startsWith('status')) {
this.addTerminalOutput(content, `
On branch main
Your branch is up to date with 'origin/main'
Changes not staged for commit:
modified: life.js (added more cat puns)
modified: happiness.css (increased by 200%)
Untracked files:
cat-treats.json
purr-sounds.wav
đ¸ Working tree status: Purrfect!`);
} else if (args.startsWith('log')) {
this.addTerminalOutput(content, `
commit a1b2c3d (HEAD -> main)
Author: CatDeveloper
Date: ${new Date().toDateString()}
Fix: Resolved all bugs with strategic cat napping
commit d4e5f6g
Author: CatDeveloper
Date: Yesterday
Add: More cat puns to error messages`);
} else {
this.addTerminalOutput(content, 'đą Git command executed! *purrs approvingly*');
}
},
terminalNpm(content, args) {
if (args.startsWith('install')) {
this.addTerminalOutput(content, `
đĻ Installing cat-packages...
đž + cat-utils@9.0.0
đ¸ + purr-framework@1.2.3
đą + meow-validator@0.5.7
đģ + treat-dispenser@2.1.0
added 42 packages in 3.14s (purr time)
đē All packages installed successfully!`);
} else if (args.startsWith('run')) {
this.addTerminalOutput(content, `đââī¸ Running npm script... *cat runs in circles*`);
} else {
this.addTerminalOutput(content, 'đĻ NPM operation completed! Dependencies are purr-fect! đ¸');
}
},
terminalHistory(content, commandHistory) {
if (commandHistory.length === 0) {
this.addTerminalOutput(content, 'History is empty... like a cat\'s promise to stay off the keyboard đ¸');
return;
}
let output = 'đ Command History:\n';
commandHistory.forEach((cmd, index) => {
output += `${index + 1}. ${cmd}\n`;
});
this.addTerminalOutput(content, output);
},
terminalEcho(content, text) {
if (!text) {
this.addTerminalOutput(content, '');
return;
}
if (text.toLowerCase().includes('cat') || text.toLowerCase().includes('meow')) {
this.addTerminalOutput(content, `${text} đ¸`);
} else {
this.addTerminalOutput(content, text);
}
},
terminalUnknown(content, command) {
const suggestions = [
`đ Command '${command}' not found! Did you mean to meow instead?`,
`đŋ '${command}' is not a valid command. Try 'help' for available commands!`,
`đą Unknown command '${command}'. Even cats make typos! Try 'help'.`,
`đ¸ '${command}'? That's not cat language! Type 'help' to see what I understand.`,
`đž Command '${command}' not recognized. Are you sure you're not a dog? đ`
];
const suggestion = suggestions[Math.floor(Math.random() * suggestions.length)];
this.addTerminalOutput(content, suggestion);
}
};
// Initialize CatOS when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
CatOS.init();
});
// Add CSS animations
const style = document.createElement('style');
style.textContent = `
@keyframes slideIn {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
@keyframes slideOut {
from {
transform: translateX(0);
opacity: 1;
}
to {
transform: translateX(100%);
opacity: 0;
}
}
.notification-content {
display: flex;
align-items: center;
gap: 8px;
}
`;
document.head.appendChild(style);
console.log('đąâđģ CatOS v9.0 (Whiskers Edition) loaded successfully!');
console.log('đĄ Try these keyboard shortcuts:');
console.log(' âĸ Alt + Tab: Switch windows');
console.log(' âĸ Ctrl + Alt + T: Open terminal');
console.log(' âĸ Escape: Close menus');