Escape Room Generator
Students must code their way out of a room. Configure the timer, background, and stages, then export a single HTML file with inline CSS + JavaScript, or hit PLAY to test it immediately.
Escape room preview
Escape RoomTimer 10:00
Room
Server Room Lockdown
4 coding stages to unlock the door.
Stage outline
- 1. Stage 1 – Fix the Syntax
- 2. Stage 2 – Click to Debug
- 3. Stage 3 – Generate Codes 0–1000
- + 1 more…
Stages
Define each coding puzzle the students must solve to escape.
Stage 1
Stage 2
Stage 3
Stage 4
Generated Escape Room HTML (inline styles only)
Copy everything, save as escape.html, put your image next to it, and open to play. Or just click PLAY on the left.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Escape Room – Server Room Lockdown</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body style="
margin:0;
font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;
color:#e5e7eb;
background-color:#020617;
background-image:url('/escape-room.jpg');
background-size:cover;
background-position:center;
background-repeat:no-repeat;
">
<div style="
min-height:100vh;
padding:24px 16px;
background:linear-gradient(to bottom right, rgba(15,23,42,0.92), rgba(15,23,42,0.96));
">
<div style="
max-width:960px;
margin:0 auto;
border-radius:24px;
border:1px solid rgba(148,163,184,0.4);
background:linear-gradient(to bottom right, rgba(15,23,42,0.98), rgba(15,23,42,0.95));
box-shadow:0 25px 80px rgba(0,0,0,0.8);
padding:20px 20px 24px 20px;
">
<header style="
margin-bottom:16px;
display:flex;
justify-content:space-between;
align-items:center;
gap:12px;
flex-wrap:wrap;
">
<div style="flex:1 1 auto;min-width:220px;">
<h1 style="margin:0 0 4px 0;font-size:26px;font-weight:700;color:#f9fafb;">
Server Room Lockdown
</h1>
<p style="margin:0;font-size:14px;color:#9ca3af;">
You are locked in. Solve each coding puzzle in order to unlock the door before the timer runs out.
</p>
</div>
<div style="
flex-shrink:0;
display:flex;
flex-direction:column;
align-items:flex-end;
gap:4px;
">
<div style="
border-radius:999px;
border:1px solid #4b5563;
padding:6px 14px;
display:flex;
align-items:center;
gap:8px;
background:#020617;
">
<div style="display:flex;flex-direction:column;">
<span style="
font-size:11px;
text-transform:uppercase;
letter-spacing:0.08em;
color:#9ca3af;
">
Time left
</span>
<span id="stage-counter" style="font-size:11px;color:#9ca3af;">
Stage 1 of 4
</span>
</div>
<span id="escape-timer" style="font-size:22px;font-weight:700;">
--:--
</span>
</div>
</div>
</header>
<main style="margin-top:8px;">
<section
data-stage-index="0"
style="
display:block;
border:1px solid #1f2937;
border-radius:16px;
padding:16px;
margin-bottom:16px;
background:rgba(15,23,42,0.92);
box-shadow:0 10px 40px rgba(0,0,0,0.6);
"
>
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:8px;">
<h2 style="margin:0;font-size:18px;font-weight:600;color:#e5e7eb;">
Stage 1 – Fix the Syntax
</h2>
<span style="font-size:11px;color:#9ca3af;text-transform:uppercase;letter-spacing:0.08em;">
Stage 1 of 4
</span>
</div>
<p style="margin:0 0 8px 0;font-size:14px;color:#cbd5f5;">
The main console is red with errors. Fix a broken JavaScript snippet so the power to the door comes back online.
</p>
<p style="margin:0 0 8px 0;font-size:13px;color:#e5e7eb;">
<strong>Task:</strong> Give the player a short JS snippet with ONE clear syntax error (like missing parenthesis or comma) and tell them to fix it.
</p>
<label style="display:block;margin-top:8px;">
<span style="display:block;margin-bottom:4px;font-size:11px;text-transform:uppercase;letter-spacing:0.08em;color:#9ca3af;">
Your answer / code
</span>
<textarea
style="
width:100%;
min-height:90px;
border-radius:12px;
border:1px solid #4b5563;
padding:8px;
font-family:ui-monospace,Menlo,Monaco,Consolas,monospace;
font-size:12px;
background-color:#020617;
color:#e5e7eb;
resize:vertical;
"
></textarea>
</label>
<p style="margin:8px 0 0 0;font-size:11px;color:#9ca3af;">
When you are happy with your answer, click the button below to move on.
</p>
</section>
<section
data-stage-index="1"
style="
display:none;
border:1px solid #1f2937;
border-radius:16px;
padding:16px;
margin-bottom:16px;
background:rgba(15,23,42,0.92);
box-shadow:0 10px 40px rgba(0,0,0,0.6);
"
>
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:8px;">
<h2 style="margin:0;font-size:18px;font-weight:600;color:#e5e7eb;">
Stage 2 – Click to Debug
</h2>
<span style="font-size:11px;color:#9ca3af;text-transform:uppercase;letter-spacing:0.08em;">
Stage 2 of 4
</span>
</div>
<p style="margin:0 0 8px 0;font-size:14px;color:#cbd5f5;">
A security camera feed shows three panels. Only one panel hides the debug console switch.
</p>
<p style="margin:0 0 8px 0;font-size:13px;color:#e5e7eb;">
<strong>Task:</strong> Describe which image / area they must click and what bug they must find and explain in the code behind that panel.
</p>
<label style="display:block;margin-top:8px;">
<span style="display:block;margin-bottom:4px;font-size:11px;text-transform:uppercase;letter-spacing:0.08em;color:#9ca3af;">
Your answer / code
</span>
<textarea
style="
width:100%;
min-height:90px;
border-radius:12px;
border:1px solid #4b5563;
padding:8px;
font-family:ui-monospace,Menlo,Monaco,Consolas,monospace;
font-size:12px;
background-color:#020617;
color:#e5e7eb;
resize:vertical;
"
></textarea>
</label>
<p style="margin:8px 0 0 0;font-size:11px;color:#9ca3af;">
When you are happy with your answer, click the button below to move on.
</p>
</section>
<section
data-stage-index="2"
style="
display:none;
border:1px solid #1f2937;
border-radius:16px;
padding:16px;
margin-bottom:16px;
background:rgba(15,23,42,0.92);
box-shadow:0 10px 40px rgba(0,0,0,0.6);
"
>
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:8px;">
<h2 style="margin:0;font-size:18px;font-weight:600;color:#e5e7eb;">
Stage 3 – Generate Codes 0–1000
</h2>
<span style="font-size:11px;color:#9ca3af;text-transform:uppercase;letter-spacing:0.08em;">
Stage 3 of 4
</span>
</div>
<p style="margin:0 0 8px 0;font-size:14px;color:#cbd5f5;">
The lock requires every code from 000 to 1000 to be tested in sequence.
</p>
<p style="margin:0 0 8px 0;font-size:13px;color:#e5e7eb;">
<strong>Task:</strong> Tell the player to write code (loop) that generates all numbers between 0 and 1000 inclusive, and briefly describe which loop construct to use.
</p>
<label style="display:block;margin-top:8px;">
<span style="display:block;margin-bottom:4px;font-size:11px;text-transform:uppercase;letter-spacing:0.08em;color:#9ca3af;">
Your answer / code
</span>
<textarea
style="
width:100%;
min-height:90px;
border-radius:12px;
border:1px solid #4b5563;
padding:8px;
font-family:ui-monospace,Menlo,Monaco,Consolas,monospace;
font-size:12px;
background-color:#020617;
color:#e5e7eb;
resize:vertical;
"
></textarea>
</label>
<p style="margin:8px 0 0 0;font-size:11px;color:#9ca3af;">
When you are happy with your answer, click the button below to move on.
</p>
</section>
<section
data-stage-index="3"
style="
display:none;
border:1px solid #1f2937;
border-radius:16px;
padding:16px;
margin-bottom:16px;
background:rgba(15,23,42,0.92);
box-shadow:0 10px 40px rgba(0,0,0,0.6);
"
>
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:8px;">
<h2 style="margin:0;font-size:18px;font-weight:600;color:#e5e7eb;">
Stage 4 – Port Data Format
</h2>
<span style="font-size:11px;color:#9ca3af;text-transform:uppercase;letter-spacing:0.08em;">
Stage 4 of 4
</span>
</div>
<p style="margin:0 0 8px 0;font-size:14px;color:#cbd5f5;">
The final door only understands JSON but your current data is in CSV.
</p>
<p style="margin:0 0 8px 0;font-size:13px;color:#e5e7eb;">
<strong>Task:</strong> Describe a small CSV example and ask the player to write pseudocode or code that turns it into a JSON array of objects.
</p>
<label style="display:block;margin-top:8px;">
<span style="display:block;margin-bottom:4px;font-size:11px;text-transform:uppercase;letter-spacing:0.08em;color:#9ca3af;">
Your answer / code
</span>
<textarea
style="
width:100%;
min-height:90px;
border-radius:12px;
border:1px solid #4b5563;
padding:8px;
font-family:ui-monospace,Menlo,Monaco,Consolas,monospace;
font-size:12px;
background-color:#020617;
color:#e5e7eb;
resize:vertical;
"
></textarea>
</label>
<p style="margin:8px 0 0 0;font-size:11px;color:#9ca3af;">
When you are happy with your answer, click the button below to move on.
</p>
</section>
</main>
<div style="
margin-top:12px;
display:flex;
justify-content:space-between;
align-items:center;
gap:8px;
flex-wrap:wrap;
">
<p style="margin:0;font-size:12px;color:#9ca3af;max-width:360px;">
Work through each stage in order. When you finish the final task, click the button to attempt your escape.
</p>
<button
id="next-stage-btn"
type="button"
style="
border-radius:999px;
border:none;
padding:10px 18px;
font-size:13px;
font-weight:600;
letter-spacing:0.04em;
text-transform:uppercase;
cursor:pointer;
background:linear-gradient(to right,#22c55e,#4ade80);
color:#022c22;
box-shadow:0 12px 30px rgba(34,197,94,0.45);
"
>
Next stage
</button>
</div>
<div
id="escape-result"
style="
margin-top:14px;
display:none;
border-radius:16px;
padding:10px 12px;
font-size:13px;
font-weight:500;
color:#f9fafb;
background:rgba(22,163,74,0.95);
"
></div>
</div>
</div>
<script>
(() => {
const totalSeconds = 10 * 60;
let remaining = totalSeconds;
let escaped = false;
const timerEl = document.getElementById('escape-timer');
const resultEl = document.getElementById('escape-result');
const nextBtn = document.getElementById('next-stage-btn');
const stageCounter = document.getElementById('stage-counter');
const stages = Array.from(document.querySelectorAll('[data-stage-index]'));
let currentStage = 0;
function updateTimerDisplay() {
if (!timerEl) return;
const m = Math.floor(remaining / 60);
const s = remaining % 60;
timerEl.textContent =
m.toString().padStart(2, '0') + ':' + s.toString().padStart(2, '0');
}
function showStage(index) {
stages.forEach((el, i) => {
if (!(el instanceof HTMLElement)) return;
el.style.display = i === index ? 'block' : 'none';
});
if (stageCounter) {
stageCounter.textContent = 'Stage ' + (index + 1) + ' of ' + stages.length;
}
if (nextBtn) {
nextBtn.textContent =
index === stages.length - 1 ? 'Escape the room' : 'Next stage';
}
}
if (!timerEl || !nextBtn || stages.length === 0) {
return;
}
showStage(currentStage);
updateTimerDisplay();
const interval = setInterval(() => {
if (escaped) return;
remaining--;
if (remaining <= 0) {
remaining = 0;
clearInterval(interval);
updateTimerDisplay();
if (resultEl) {
resultEl.style.display = 'block';
resultEl.textContent =
'Time is up! The door remains locked and the room goes dark.';
resultEl.style.background = 'rgba(127,29,29,0.95)';
}
nextBtn.disabled = true;
} else {
updateTimerDisplay();
}
}, 1000);
nextBtn.addEventListener('click', function () {
if (escaped) return;
if (currentStage < stages.length - 1) {
currentStage++;
showStage(currentStage);
} else {
escaped = true;
clearInterval(interval);
if (resultEl) {
resultEl.style.display = 'block';
resultEl.textContent =
'You escaped! You solved all coding challenges before the timer hit zero.';
resultEl.style.background = 'rgba(22,163,74,0.95)';
}
}
});
})();
</script>
</body>
</html>