Skip to content

Commit 75f36d6

Browse files
anushka11panushkajagdish-15github-actions[bot]
authored
added 404 website themed page (#102)
* added 404 website themed page * refine 404 page layout and responsiveness * style: auto-format code with Prettier (/format) * fix: improve mobile responsiveness on 404 page for small screens * Remove cursor effect from 404 title * style: auto-format code with Prettier (/format) --------- Co-authored-by: anushka <anushka11@example.com> Co-authored-by: Jagdish Prajapati <jagadishdrp@gmail.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 99474c4 commit 75f36d6

2 files changed

Lines changed: 311 additions & 1 deletion

File tree

frontend/404.html

Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>404 — Not Found | CodePVG</title>
7+
<link rel="icon" type="image/png" href="assets/logo.png" />
8+
<link rel="preconnect" href="https://fonts.googleapis.com" />
9+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
10+
<link
11+
href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Space+Mono:wght@400;700&family=Share+Tech+Mono&display=swap"
12+
rel="stylesheet"
13+
/>
14+
<link rel="stylesheet" href="styles/main.css" />
15+
<style>
16+
/* 404-specific overrides */
17+
body {
18+
background: var(--bg);
19+
color: var(--green);
20+
font-family: "Share Tech Mono", "Courier New", monospace;
21+
min-height: 100vh;
22+
display: flex;
23+
align-items: center;
24+
justify-content: center;
25+
overflow: hidden;
26+
position: relative;
27+
}
28+
29+
/* Matrix rain canvas */
30+
#matrix {
31+
position: fixed;
32+
top: 0;
33+
left: 0;
34+
width: 100%;
35+
height: 100%;
36+
z-index: 0;
37+
opacity: 0.18;
38+
}
39+
40+
/* Main panel */
41+
.panel {
42+
position: relative;
43+
z-index: 1;
44+
background: rgba(0, 10, 0, 0.85);
45+
border: 1px solid rgba(0, 255, 65, 0.3);
46+
border-radius: 4px;
47+
padding: 2.5rem 3rem;
48+
max-width: 680px;
49+
width: 90%;
50+
box-shadow:
51+
0 0 40px rgba(0, 255, 65, 0.08),
52+
inset 0 0 60px rgba(0, 0, 0, 0.5);
53+
}
54+
55+
/* Title */
56+
.title {
57+
font-size: 2.4rem;
58+
font-weight: normal;
59+
color: var(--green);
60+
text-shadow:
61+
0 0 20px rgba(0, 255, 65, 0.4),
62+
0 0 40px rgba(0, 255, 65, 0.4);
63+
letter-spacing: 2px;
64+
margin-bottom: 0.4rem;
65+
}
66+
67+
@keyframes blink {
68+
50% {
69+
opacity: 0;
70+
}
71+
}
72+
73+
.subtitle {
74+
color: #4a8c4a;
75+
font-size: 0.85rem;
76+
margin-bottom: 2rem;
77+
}
78+
79+
/* Terminal lines */
80+
.terminal-block {
81+
margin-bottom: 1.4rem;
82+
}
83+
84+
.line {
85+
line-height: 1.8;
86+
font-size: 0.95rem;
87+
}
88+
89+
.prompt {
90+
color: var(--green);
91+
text-shadow: 0 0 8px rgba(0, 255, 65, 0.4);
92+
}
93+
94+
.prompt-sym {
95+
color: var(--green-dim);
96+
}
97+
98+
.cmd {
99+
color: #c9e8c9;
100+
}
101+
102+
.error-line {
103+
color: var(--red);
104+
text-shadow: 0 0 8px rgba(255, 68, 68, 0.4);
105+
}
106+
107+
.comment {
108+
color: #4a8c4a;
109+
}
110+
111+
.highlight {
112+
color: var(--green);
113+
font-weight: bold;
114+
text-shadow: 0 0 10px rgba(0, 255, 65, 0.4);
115+
}
116+
117+
.highlight a {
118+
color: inherit;
119+
text-decoration: none;
120+
transition: color 0.15s ease;
121+
}
122+
123+
.highlight a:hover {
124+
color: #66ffaa;
125+
text-shadow: 0 0 12px rgba(0, 255, 65, 0.4);
126+
}
127+
128+
/* Divider */
129+
.divider {
130+
border: none;
131+
border-top: 1px solid rgba(0, 255, 65, 0.3);
132+
margin: 1.4rem 0;
133+
}
134+
135+
/* Button area — centered */
136+
.nav-links {
137+
display: flex;
138+
gap: 1.2rem;
139+
flex-wrap: wrap;
140+
margin-top: 1.8rem;
141+
justify-content: center;
142+
}
143+
144+
/* Scanline overlay */
145+
body::after {
146+
content: "";
147+
position: fixed;
148+
top: 0;
149+
left: 0;
150+
width: 100%;
151+
height: 100%;
152+
background: repeating-linear-gradient(
153+
0deg,
154+
transparent,
155+
transparent 2px,
156+
rgba(0, 0, 0, 0.05) 2px,
157+
rgba(0, 0, 0, 0.05) 4px
158+
);
159+
pointer-events: none;
160+
z-index: 2;
161+
}
162+
@media (max-width: 480px) {
163+
.panel {
164+
padding: 1.5rem 1.2rem;
165+
width: 95%;
166+
}
167+
.title {
168+
font-size: 1.6rem;
169+
}
170+
171+
.subtitle {
172+
font-size: 0.75rem;
173+
}
174+
.line {
175+
font-size: 0.82rem;
176+
line-height: 1.6;
177+
}
178+
.nav-links {
179+
flex-direction: column;
180+
gap: 0.75rem;
181+
}
182+
.nav-links a {
183+
text-align: center;
184+
width: 100%;
185+
box-sizing: border-box;
186+
}
187+
}
188+
</style>
189+
</head>
190+
191+
<body>
192+
<canvas id="matrix"></canvas>
193+
194+
<div class="panel">
195+
<div class="title">404 — Not Found</div>
196+
<div class="subtitle">
197+
&gt; route resolution failed. filesystem integrity nominal.
198+
</div>
199+
200+
<hr class="divider" />
201+
202+
<div class="terminal-block">
203+
<div class="line">
204+
<span class="prompt">guest@codepvg</span
205+
><span class="prompt-sym">:~$</span>
206+
<span class="cmd" id="cd-line"> cd /unknown-path</span>
207+
</div>
208+
<div class="line error-line">
209+
bash: cd: <span id="path-display">/unknown-path</span>: No such file
210+
or directory
211+
</div>
212+
</div>
213+
214+
<div class="terminal-block">
215+
<div class="line comment"># exit code: 404</div>
216+
<div class="line comment">
217+
# This route doesn't exist. Unlike your rank, which does.
218+
</div>
219+
</div>
220+
221+
<hr class="divider" />
222+
223+
<div class="terminal-block">
224+
<div class="line">
225+
<span class="prompt">guest@codepvg</span
226+
><span class="prompt-sym">:~$</span>
227+
<span class="cmd"> ls /valid-routes</span>
228+
</div>
229+
<div class="line" style="padding-left: 1.2rem">
230+
<span class="highlight"><a href="/leaderboard">leaderboard/</a></span>
231+
&nbsp;&nbsp;
232+
<span class="highlight"
233+
><a href="/registration">registration/</a></span
234+
>
235+
&nbsp;&nbsp;
236+
<span class="highlight"><a href="/about">about/</a></span>
237+
</div>
238+
</div>
239+
240+
<div class="line">
241+
<span class="prompt">guest@codepvg</span
242+
><span class="prompt-sym">:~$</span>
243+
<span
244+
class="cursor"
245+
style="
246+
width: 9px;
247+
height: 1rem;
248+
background: var(--green);
249+
display: inline-block;
250+
vertical-align: middle;
251+
margin-left: 6px;
252+
animation: blink 1s step-end infinite;
253+
"
254+
></span>
255+
</div>
256+
257+
<div class="nav-links">
258+
<a href="/leaderboard" class="btn btn-primary">view_leaderboard</a>
259+
<a href="/registration" class="btn btn-secondary">register_now</a>
260+
</div>
261+
</div>
262+
263+
<script>
264+
// Inject actual bad path
265+
const p = window.location.pathname;
266+
document.getElementById("cd-line").textContent = " cd " + p;
267+
document.getElementById("path-display").textContent = p;
268+
269+
// Matrix rain
270+
const canvas = document.getElementById("matrix");
271+
const ctx = canvas.getContext("2d");
272+
273+
function resize() {
274+
canvas.width = window.innerWidth;
275+
canvas.height = window.innerHeight;
276+
}
277+
resize();
278+
window.addEventListener("resize", resize);
279+
280+
const chars =
281+
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%^&*()アイウエオカキクケコサシスセソタチツテトナニヌネノ";
282+
const fontSize = 14;
283+
let cols = Math.floor(canvas.width / fontSize);
284+
let drops = Array(cols).fill(1);
285+
286+
function drawMatrix() {
287+
ctx.fillStyle = "rgba(0, 0, 0, 0.05)";
288+
ctx.fillRect(0, 0, canvas.width, canvas.height);
289+
290+
ctx.fillStyle = "#00ff41";
291+
ctx.font = fontSize + "px Share Tech Mono, monospace";
292+
293+
cols = Math.floor(canvas.width / fontSize);
294+
if (drops.length < cols)
295+
drops = drops.concat(Array(cols - drops.length).fill(1));
296+
297+
for (let i = 0; i < cols; i++) {
298+
const char = chars[Math.floor(Math.random() * chars.length)];
299+
ctx.fillText(char, i * fontSize, drops[i] * fontSize);
300+
if (drops[i] * fontSize > canvas.height && Math.random() > 0.975)
301+
drops[i] = 0;
302+
drops[i]++;
303+
}
304+
}
305+
306+
setInterval(drawMatrix, 40);
307+
</script>
308+
</body>
309+
</html>

server.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,9 @@ app.get("/api/student/:username", async (req, res) => {
150150
}
151151
});
152152

153+
// 404 handler
153154
app.use((req, res) => {
154-
res.status(404).send("Page not found");
155+
res.status(404).sendFile(path.join(__dirname, "frontend", "404.html"));
155156
});
156157

157158
app.listen(PORT, () => {

0 commit comments

Comments
 (0)