Skip to content

Instantly share code, notes, and snippets.

@Shadhujan
Created January 9, 2026 00:21
Show Gist options
  • Select an option

  • Save Shadhujan/91fed5757e310bda0ac3fc83dc34b7b2 to your computer and use it in GitHub Desktop.

Select an option

Save Shadhujan/91fed5757e310bda0ac3fc83dc34b7b2 to your computer and use it in GitHub Desktop.
Interactive Windows 95 Simulation (Single File HTML/CSS/JS) - Demo for 'Gist Host' Hack
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Windows 95</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
/* --- RESET & FONTS --- */
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
overflow: hidden;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; /* Fallback for MS Sans Serif */
background-color: #008080; /* Classic Teal */
user-select: none;
height: 100vh;
width: 100vw;
cursor: default;
}
/* --- UTILITIES for the 3D Look --- */
.win95-border {
background-color: #c0c0c0;
border-top: 2px solid #dfdfdf;
border-left: 2px solid #dfdfdf;
border-right: 2px solid #000000;
border-bottom: 2px solid #000000;
box-shadow: 1px 1px 0px #ffffff inset, -1px -1px 0px #808080 inset;
}
.win95-inset {
background-color: #fff;
border-top: 2px solid #808080;
border-left: 2px solid #808080;
border-right: 2px solid #fff;
border-bottom: 2px solid #fff;
box-shadow: 1px 1px 0px #000 inset;
}
.win95-btn {
font-family: Tahoma, sans-serif;
font-weight: bold;
font-size: 12px;
color: black;
background: #c0c0c0;
border-top: 1px solid #fff;
border-left: 1px solid #fff;
border-right: 1px solid #000;
border-bottom: 1px solid #000;
box-shadow: 1px 1px 0 #808080;
padding: 2px 6px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
.win95-btn:active, .win95-btn.active {
border-top: 1px solid #000;
border-left: 1px solid #000;
border-right: 1px solid #fff;
border-bottom: 1px solid #fff;
box-shadow: 1px 1px 0 #808080 inset;
transform: translate(1px, 1px);
}
/* --- DESKTOP ICONS --- */
#desktop {
width: 100%;
height: calc(100% - 30px); /* Minus taskbar */
position: relative;
padding: 10px;
display: flex;
flex-direction: column;
flex-wrap: wrap;
align-content: flex-start;
gap: 20px;
}
.desktop-icon {
width: 70px;
text-align: center;
color: white;
cursor: pointer;
display: flex;
flex-direction: column;
align-items: center;
}
.desktop-icon i {
font-size: 32px;
margin-bottom: 5px;
text-shadow: 1px 1px 0 #000;
}
.desktop-icon span {
font-size: 12px;
background: transparent;
padding: 2px;
}
.desktop-icon:active span, .desktop-icon.selected span {
background-color: #000080;
border: 1px dotted #fff;
}
/* --- START MENU --- */
#start-menu {
position: absolute;
bottom: 32px;
left: 2px;
width: 200px;
background: #c0c0c0;
display: none;
z-index: 9999;
padding: 2px;
}
.sidebar-strip {
width: 25px;
background: #000080;
position: absolute;
left: 2px;
top: 2px;
bottom: 2px;
display: flex;
align-items: flex-end;
}
.sidebar-text {
transform: rotate(-90deg);
color: #c0c0c0;
font-size: 20px;
font-weight: bold;
white-space: nowrap;
margin-bottom: 10px;
margin-left: -5px;
}
.menu-items {
margin-left: 28px;
}
.menu-item {
padding: 8px 10px;
display: flex;
align-items: center;
font-size: 12px;
cursor: pointer;
color: #000;
}
.menu-item:hover {
background-color: #000080;
color: white;
}
.menu-item i {
margin-right: 10px;
width: 20px;
text-align: center;
}
.menu-divider {
height: 1px;
background: #808080;
border-bottom: 1px solid #fff;
margin: 4px 0;
}
/* --- TASKBAR --- */
#taskbar {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 30px;
background: #c0c0c0;
border-top: 2px solid #fff;
display: flex;
align-items: center;
padding: 2px;
z-index: 10000;
}
#start-btn {
height: 22px;
padding: 0 8px;
display: flex;
align-items: center;
gap: 5px;
margin-right: 5px;
font-weight: bold;
font-style: italic;
}
#task-list {
flex-grow: 1;
display: flex;
gap: 4px;
padding-left: 4px;
overflow: hidden;
}
.task-item {
width: 160px;
height: 22px;
display: flex;
align-items: center;
padding: 0 5px;
font-size: 11px;
text-align: left;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.task-item img, .task-item i {
margin-right: 5px;
}
#tray {
width: 70px;
height: 22px;
background: #c0c0c0;
border-top: 1px solid #808080;
border-left: 1px solid #808080;
border-right: 1px solid #fff;
border-bottom: 1px solid #fff;
display: flex;
align-items: center;
justify-content: center;
font-size: 11px;
margin-left: 5px;
}
/* --- WINDOWS --- */
.window {
position: absolute;
background: #c0c0c0;
padding: 3px;
display: flex;
flex-direction: column;
min-width: 200px;
min-height: 100px;
box-shadow: 2px 2px 10px rgba(0,0,0,0.4);
}
.title-bar {
background: linear-gradient(90deg, #000080, #1084d0);
color: white;
padding: 2px 4px;
font-weight: bold;
font-size: 12px;
display: flex;
justify-content: space-between;
align-items: center;
cursor: default;
}
.window.inactive .title-bar {
background: #808080;
color: #c0c0c0;
}
.title-controls {
display: flex;
gap: 2px;
}
.control-btn {
width: 16px;
height: 14px;
font-size: 10px;
line-height: 10px;
text-align: center;
padding: 0;
background: #c0c0c0;
}
.window-menu {
display: flex;
padding: 2px 0;
font-size: 12px;
}
.window-menu span {
padding: 0 6px;
cursor: pointer;
}
.window-menu span:hover {
background: #000080;
color: white;
}
.window-menu span u {
text-decoration: underline;
}
.window-content {
flex-grow: 1;
margin-top: 2px;
overflow: auto;
font-family: 'Courier New', Courier, monospace;
font-size: 14px;
}
/* Specific App Styles */
.notepad-area {
width: 100%;
height: 100%;
resize: none;
border: none;
outline: none;
font-family: 'Fixedsys', 'Courier New', monospace;
padding: 5px;
}
/* Minesweeper */
.minesweeper-header {
background: #c0c0c0;
padding: 5px;
display: flex;
justify-content: space-between;
border: 2px solid #808080;
border-right-color: #fff;
border-bottom-color: #fff;
margin-bottom: 5px;
}
.mine-lcd {
background: black;
color: red;
font-family: 'Courier New', monospace;
font-weight: bold;
font-size: 18px;
padding: 0 4px;
}
.mine-face {
width: 24px;
height: 24px;
font-size: 16px;
padding: 0;
}
.mine-grid {
display: grid;
grid-template-columns: repeat(9, 20px);
grid-template-rows: repeat(9, 20px);
border-top: 3px solid #808080;
border-left: 3px solid #808080;
border-right: 3px solid #fff;
border-bottom: 3px solid #fff;
}
.mine-cell {
width: 20px;
height: 20px;
background: #c0c0c0;
border-top: 2px solid #fff;
border-left: 2px solid #fff;
border-right: 2px solid #808080;
border-bottom: 2px solid #808080;
font-size: 12px;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
cursor: default;
}
.mine-cell.revealed {
border: 1px solid #808080;
background: #c0c0c0;
}
.mine-cell.bomb {
background: red;
}
/* Explorer */
.explorer-body {
background: white;
padding: 10px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(60px, 1fr));
gap: 10px;
}
.explorer-item {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
font-size: 11px;
cursor: pointer;
color: black;
}
.explorer-item i {
font-size: 24px;
margin-bottom: 4px;
color: #000080; /* Folder color */
}
.explorer-item:hover span {
background: #000080;
color: white;
}
</style>
</head>
<body>
<!-- DESKTOP -->
<div id="desktop">
<div class="desktop-icon" ondblclick="openWindow('myComputer')">
<i class="fa-solid fa-computer"></i>
<span>My Computer</span>
</div>
<div class="desktop-icon" ondblclick="openWindow('recycle')">
<i class="fa-solid fa-trash-can"></i>
<span>Recycle Bin</span>
</div>
<div class="desktop-icon" ondblclick="openWindow('notepad')">
<i class="fa-solid fa-note-sticky"></i>
<span>Notepad</span>
</div>
<div class="desktop-icon" ondblclick="openWindow('minesweeper')">
<i class="fa-solid fa-bomb"></i>
<span>Minesweeper</span>
</div>
<div class="desktop-icon" ondblclick="openWindow('internet')">
<i class="fa-brands fa-internet-explorer"></i>
<span>Internet</span>
</div>
<div class="desktop-icon" ondblclick="openWindow('readme')">
<i class="fa-solid fa-file-lines"></i>
<span>README.TXT</span>
</div>
</div>
<!-- START MENU -->
<div id="start-menu" class="win95-border">
<div class="sidebar-strip"><div class="sidebar-text">Windows 95</div></div>
<div class="menu-items">
<div class="menu-item" onclick="openWindow('notepad')"><i class="fa-solid fa-note-sticky"></i>Programs</div>
<div class="menu-item"><i class="fa-solid fa-folder-open"></i>Documents</div>
<div class="menu-item"><i class="fa-solid fa-gear"></i>Settings</div>
<div class="menu-item"><i class="fa-solid fa-magnifying-glass"></i>Find</div>
<div class="menu-item"><i class="fa-solid fa-circle-question"></i>Help</div>
<div class="menu-item" onclick="openWindow('run')"><i class="fa-solid fa-person-running"></i>Run...</div>
<div class="menu-divider"></div>
<div class="menu-item" onclick="alert('It is now safe to turn off your computer.')"><i class="fa-solid fa-power-off"></i>Shut Down...</div>
</div>
</div>
<!-- WINDOW CONTAINER -->
<div id="window-container"></div>
<!-- TASKBAR -->
<div id="taskbar">
<div id="start-btn" class="win95-btn" onclick="toggleStartMenu()">
<i class="fa-brands fa-windows"></i> Start
</div>
<div class="menu-divider" style="width: 2px; height: 20px; margin: 0 4px; border-left: 1px solid #808080; border-right: 1px solid #fff;"></div>
<div id="task-list">
<!-- Task items go here -->
</div>
<div id="tray">12:00 PM</div>
</div>
<script>
/* --- SYSTEM STATE --- */
let zIndexCounter = 100;
const startMenu = document.getElementById('start-menu');
const startBtn = document.getElementById('start-btn');
const windowContainer = document.getElementById('window-container');
const taskList = document.getElementById('task-list');
/* --- CLOCK --- */
function updateClock() {
const now = new Date();
let hours = now.getHours();
const minutes = now.getMinutes().toString().padStart(2, '0');
const ampm = hours >= 12 ? 'PM' : 'AM';
hours = hours % 12;
hours = hours ? hours : 12;
document.getElementById('tray').textContent = `${hours}:${minutes} ${ampm}`;
}
setInterval(updateClock, 1000);
updateClock();
/* --- START MENU LOGIC --- */
function toggleStartMenu() {
const isVisible = startMenu.style.display === 'block';
startMenu.style.display = isVisible ? 'none' : 'block';
startBtn.classList.toggle('active', !isVisible);
}
document.addEventListener('click', (e) => {
if (!startMenu.contains(e.target) && !startBtn.contains(e.target)) {
startMenu.style.display = 'none';
startBtn.classList.remove('active');
}
});
/* --- WINDOW SYSTEM --- */
const apps = {
'notepad': {
title: 'Untitled - Notepad',
icon: 'fa-note-sticky',
width: 400,
height: 300,
content: `<div class="win95-inset" style="height:100%;"><textarea class="notepad-area" placeholder="Type here..."></textarea></div>`,
menu: true
},
'myComputer': {
title: 'My Computer',
icon: 'fa-computer',
width: 500,
height: 350,
content: `
<div class="win95-inset explorer-body" style="height:100%;">
<div class="explorer-item"><i class="fa-solid fa-floppy-disk"></i><span>3Β½ Floppy (A:)</span></div>
<div class="explorer-item"><i class="fa-solid fa-hard-drive"></i><span>(C:)</span></div>
<div class="explorer-item"><i class="fa-solid fa-compact-disc"></i><span>(D:)</span></div>
<div class="explorer-item"><i class="fa-solid fa-screwdriver-wrench"></i><span>Control Panel</span></div>
<div class="explorer-item"><i class="fa-solid fa-print"></i><span>Printers</span></div>
</div>
`,
menu: true
},
'recycle': {
title: 'Recycle Bin',
icon: 'fa-trash-can',
width: 400,
height: 300,
content: `<div class="win95-inset explorer-body" style="height:100%;"><p style="width:100%; padding:10px;">The Recycle Bin is empty.</p></div>`,
menu: true
},
'internet': {
title: 'Internet Explorer',
icon: 'fa-brands fa-internet-explorer',
width: 600,
height: 450,
content: `
<div style="display:flex; flex-direction:column; height:100%;">
<div style="padding:4px; background:#c0c0c0; border-bottom:1px solid #808080;">
Address: <input type="text" value="http://www.microsoft.com" style="width:80%;">
</div>
<div class="win95-inset" style="flex-grow:1; background:white; padding:20px; overflow:auto;">
<h1>Welcome to the Internet!</h1>
<p>Under Construction.</p>
<hr>
<p style="color:blue; text-decoration:underline; cursor:pointer;">Click here to search</p>
<br>
<center><i class="fa-solid fa-triangle-exclamation" style="font-size:48px; color:#ffd700;"></i></center>
</div>
</div>
`,
menu: true
},
'readme': {
title: 'README.TXT - Notepad',
icon: 'fa-file-lines',
width: 400,
height: 300,
content: `<div class="win95-inset" style="height:100%;"><textarea class="notepad-area">Welcome to Windows 95 Mockup!
Created as a single HTML file artifact.
Features:
- Drag and Drop
- Minesweeper Game
- Functional Start Menu
- Taskbar logic
Enjoy the nostalgia!
</textarea></div>`,
menu: true
},
'minesweeper': {
title: 'Minesweeper',
icon: 'fa-bomb',
width: 206,
height: 300, // Auto adjusts
menu: true,
init: initMinesweeper,
content: `
<div id="mine-container" style="background:#c0c0c0; padding:5px;">
<div class="minesweeper-header" class="win95-inset">
<div class="mine-lcd" id="mine-count">010</div>
<button class="win95-btn mine-face" onclick="resetMinesweeper()"><i class="fa-solid fa-face-smile" style="color:#ffd700; text-shadow:1px 1px 0 #000;"></i></button>
<div class="mine-lcd" id="mine-timer">000</div>
</div>
<div class="mine-grid" id="mine-grid"></div>
</div>
`
},
'run': {
title: 'Run',
icon: 'fa-person-running',
width: 350,
height: 180,
menu: false,
content: `
<div style="padding:15px; display:flex; gap:10px; align-items:center;">
<i class="fa-solid fa-person-running" style="font-size:32px;"></i>
<div>
<p style="font-size:12px; margin:0 0 5px 0;">Type the name of a program, folder, document, or Internet resource, and Windows will open it for you.</p>
<p style="font-size:12px;">Open: <input type="text" style="width:200px;"></p>
</div>
</div>
<div style="display:flex; justify-content:flex-end; gap:5px; padding-right:10px;">
<button class="win95-btn" style="width:70px;" onclick="closeWindow(this.closest('.window').id)">OK</button>
<button class="win95-btn" style="width:70px;" onclick="closeWindow(this.closest('.window').id)">Cancel</button>
<button class="win95-btn" style="width:70px;">Browse...</button>
</div>
`
}
};
function openWindow(appId) {
const app = apps[appId];
if(!app) return;
const id = 'win-' + Date.now();
const win = document.createElement('div');
win.className = 'window win95-border';
win.id = id;
win.style.width = app.width + 'px';
win.style.height = app.height + 'px';
// Center randomish
win.style.top = (50 + Math.random() * 50) + 'px';
win.style.left = (50 + Math.random() * 50) + 'px';
win.style.zIndex = ++zIndexCounter;
// Menubar HTML
const menuHtml = app.menu ? `
<div class="window-menu">
<span><u>F</u>ile</span>
<span><u>E</u>dit</span>
<span><u>V</u>iew</span>
<span><u>H</u>elp</span>
</div>
` : '';
win.innerHTML = `
<div class="title-bar" onmousedown="startDrag(event, '${id}')">
<div style="display:flex; align-items:center; gap:5px;">
<i class="fa-solid ${app.icon}"></i> ${app.title}
</div>
<div class="title-controls">
<button class="win95-btn control-btn" onclick="minimizeWindow('${id}')">_</button>
<button class="win95-btn control-btn" onclick="maximizeWindow('${id}')">β–‘</button>
<button class="win95-btn control-btn" onclick="closeWindow('${id}')">X</button>
</div>
</div>
${menuHtml}
<div class="window-content">
${app.content}
</div>
`;
// Focus listener
win.addEventListener('mousedown', () => focusWindow(id));
windowContainer.appendChild(win);
addTaskbarItem(id, app.title, app.icon);
// Init scripts if any (like minesweeper)
if(app.init) app.init(win);
// Close start menu
startMenu.style.display = 'none';
startBtn.classList.remove('active');
}
function closeWindow(id) {
const win = document.getElementById(id);
if(win) win.remove();
const task = document.getElementById('task-' + id);
if(task) task.remove();
}
function focusWindow(id) {
const win = document.getElementById(id);
if(win) {
win.style.zIndex = ++zIndexCounter;
// Update taskbar styles
document.querySelectorAll('.task-item').forEach(t => t.classList.remove('active'));
const task = document.getElementById('task-' + id);
if(task) task.classList.add('active');
// Visual title bar update
document.querySelectorAll('.window').forEach(w => w.classList.add('inactive'));
win.classList.remove('inactive');
}
}
function minimizeWindow(id) {
const win = document.getElementById(id);
win.style.display = 'none';
const task = document.getElementById('task-' + id);
task.classList.remove('active');
}
function maximizeWindow(id) {
const win = document.getElementById(id);
if(win.style.width === '100%') {
// Restore (naive implementation, resets to default)
win.style.width = apps[Object.keys(apps).find(key => win.innerHTML.includes(apps[key].title))].width + 'px'; // Hacky finding original size
win.style.height = 'auto';
win.style.top = '50px';
win.style.left = '50px';
} else {
win.style.width = '100%';
win.style.height = 'calc(100% - 32px)'; // Minus taskbar
win.style.top = '0';
win.style.left = '0';
}
}
function addTaskbarItem(id, title, icon) {
const item = document.createElement('div');
item.className = 'task-item win95-btn active';
item.id = 'task-' + id;
item.innerHTML = `<i class="fa-solid ${icon}"></i> ${title}`;
item.onclick = () => {
const win = document.getElementById(id);
if (win.style.display === 'none') {
win.style.display = 'flex';
focusWindow(id);
} else if (item.classList.contains('active')) {
minimizeWindow(id);
} else {
focusWindow(id);
}
};
taskList.appendChild(item);
}
/* --- DRAGGING --- */
let isDragging = false;
let dragOffsetX = 0;
let dragOffsetY = 0;
let draggedWindow = null;
function startDrag(e, id) {
if(e.target.tagName === 'BUTTON') return; // Don't drag if clicking controls
isDragging = true;
draggedWindow = document.getElementById(id);
focusWindow(id);
const rect = draggedWindow.getBoundingClientRect();
dragOffsetX = e.clientX - rect.left;
dragOffsetY = e.clientY - rect.top;
}
document.addEventListener('mousemove', (e) => {
if (isDragging && draggedWindow) {
draggedWindow.style.left = (e.clientX - dragOffsetX) + 'px';
draggedWindow.style.top = (e.clientY - dragOffsetY) + 'px';
}
});
document.addEventListener('mouseup', () => {
isDragging = false;
draggedWindow = null;
});
/* --- MINESWEEPER LOGIC --- */
let mineGrid = [];
let mineGameOver = false;
function initMinesweeper(win) {
resetMinesweeper();
}
function resetMinesweeper() {
const gridEl = document.getElementById('mine-grid');
if(!gridEl) return;
gridEl.innerHTML = '';
mineGrid = [];
mineGameOver = false;
document.querySelector('.mine-face i').className = "fa-solid fa-face-smile";
// Initialize 9x9
for(let i=0; i<81; i++) {
const cell = document.createElement('div');
cell.className = 'mine-cell';
cell.dataset.idx = i;
cell.onclick = () => clickMineCell(i);
cell.oncontextmenu = (e) => { e.preventDefault(); flagMineCell(i); };
gridEl.appendChild(cell);
mineGrid.push({ isBomb: false, revealed: false, flagged: false, neighbors: 0, el: cell });
}
// Place 10 bombs
let bombsPlaced = 0;
while(bombsPlaced < 10) {
let idx = Math.floor(Math.random() * 81);
if(!mineGrid[idx].isBomb) {
mineGrid[idx].isBomb = true;
bombsPlaced++;
}
}
// Calculate numbers
for(let i=0; i<81; i++) {
if(mineGrid[i].isBomb) continue;
let neighbors = 0;
const r = Math.floor(i/9);
const c = i%9;
for(let dr=-1; dr<=1; dr++) {
for(let dc=-1; dc<=1; dc++) {
const nr = r+dr, nc = c+dc;
if(nr>=0 && nr<9 && nc>=0 && nc<9) {
if(mineGrid[nr*9+nc].isBomb) neighbors++;
}
}
}
mineGrid[i].neighbors = neighbors;
}
}
function clickMineCell(idx) {
if(mineGameOver || mineGrid[idx].revealed || mineGrid[idx].flagged) return;
const cell = mineGrid[idx];
cell.revealed = true;
cell.el.classList.add('revealed');
if(cell.isBomb) {
cell.el.classList.add('bomb');
cell.el.innerHTML = '<i class="fa-solid fa-bomb"></i>';
mineGameOver = true;
document.querySelector('.mine-face i').className = "fa-solid fa-face-dizzy";
revealAll();
} else {
if(cell.neighbors > 0) {
cell.el.textContent = cell.neighbors;
// Colors
const colors = ['blue', 'green', 'red', 'purple', 'maroon', 'turquoise', 'black', 'gray'];
cell.el.style.color = colors[cell.neighbors-1];
} else {
// Flood fill
const r = Math.floor(idx/9);
const c = idx%9;
for(let dr=-1; dr<=1; dr++) {
for(let dc=-1; dc<=1; dc++) {
const nr = r+dr, nc = c+dc;
if(nr>=0 && nr<9 && nc>=0 && nc<9) {
clickMineCell(nr*9+nc);
}
}
}
}
}
}
function flagMineCell(idx) {
if(mineGameOver || mineGrid[idx].revealed) return;
const cell = mineGrid[idx];
cell.flagged = !cell.flagged;
cell.el.innerHTML = cell.flagged ? '<i class="fa-solid fa-flag" style="color:red;"></i>' : '';
}
function revealAll() {
mineGrid.forEach(c => {
if(c.isBomb) {
c.el.classList.add('revealed', 'bomb');
c.el.innerHTML = '<i class="fa-solid fa-bomb"></i>';
}
});
}
</script>
</body>
</html>
@Shadhujan

Shadhujan commented Jan 9, 2026

Copy link
Copy Markdown
Author

This file contains a full Windows 95 simulation with a working Minesweeper game.

πŸ›‘ If you are reading this on GitHub: You are just seeing raw code because GitHub forces text/plain headers.

🟒 To see it LIVE (The Hack): Click here to render it as a real website using GistHost: https://gisthost.github.io/?91fed5757e310bda0ac3fc83dc34b7b2

This demonstrates Hack #1 from my blog: turning a static Gist into a live web host.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment