Compare commits
No commits in common. "8aa281e1f4362ec5b67d29ec9486581c9be0c13d" and "9873502b0850eff1cead090546031acdc7c3e390" have entirely different histories.
8aa281e1f4
...
9873502b08
6 changed files with 16 additions and 2475 deletions
28
README.md
28
README.md
|
@ -3,31 +3,3 @@
|
||||||
[![Netlify Status](https://api.netlify.com/api/v1/badges/7821f152-5b28-4dec-9d98-035a18e8a57a/deploy-status)](https://app.netlify.com/sites/tdpeuter-down/deploys)
|
[![Netlify Status](https://api.netlify.com/api/v1/badges/7821f152-5b28-4dec-9d98-035a18e8a57a/deploy-status)](https://app.netlify.com/sites/tdpeuter-down/deploys)
|
||||||
|
|
||||||
Ultra simple website to tell people a service is down
|
Ultra simple website to tell people a service is down
|
||||||
|
|
||||||
## Starting the website
|
|
||||||
|
|
||||||
```shell
|
|
||||||
npm run start
|
|
||||||
```
|
|
||||||
|
|
||||||
## Setup networking
|
|
||||||
|
|
||||||
### Using [Cloudflare](https://dash.cloudflare.com)
|
|
||||||
|
|
||||||
If you want to use Cloudflare to handle redirection to the website, you can use [Page Rules](https://developers.cloudflare.com/support/page-rules/).
|
|
||||||
|
|
||||||
First, make sure the DNS records for the (sub-) domains you want to redirect are [being proxied through Cloudflare](https://developers.cloudflare.com/dns/manage-dns-records/reference/proxied-dns-records). Then, head over to [Redirect Rules](https://developers.cloudflare.com/rules/url-forwarding/) (Page Rules are harder to configure, and it seems like [Cloudflare itself is more keen of Redirect Rules too](https://developers.cloudflare.com/support/page-rules/recommended-page-rules-to-consider/)).
|
|
||||||
|
|
||||||
Create a Single Redirect rule that looks similar to:
|
|
||||||
|
|
||||||
```
|
|
||||||
# When incoming requests match...
|
|
||||||
(http.host in {"example.com" "another.example.com"})
|
|
||||||
|
|
||||||
# Then URL redirect
|
|
||||||
Dynamic
|
|
||||||
concat("https://your.host.tdl/?destination=", http.request.full_uri)
|
|
||||||
302
|
|
||||||
```
|
|
||||||
|
|
||||||
Enable the rule and everything should be set!
|
|
19
index.html
19
index.html
|
@ -1,32 +1,21 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8"/>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<meta name="robots" content="noindex">
|
|
||||||
|
|
||||||
<title>Service unavailable</title>
|
<title>Service unavailable</title>
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="style.css">
|
<link rel="stylesheet" type="text/css" href="style.css">
|
||||||
<link rel="shortcut icon" type="image/png" href="assets/icon.jpg">
|
<link rel="shortcut icon" type="image/png" href="assets/icon.jpg">
|
||||||
|
<meta name="color-scheme" content="light dark">
|
||||||
|
<meta name="robots" content="noindex">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<main>
|
|
||||||
<h1>Oh, no!</h1>
|
<h1>Oh, no!</h1>
|
||||||
<p>The website you are trying to reach is currently down. Your URL works, but the system is in maintenance and/or powered off temporarily.</p>
|
<p>The website you are trying to reach is currently down. Your URL works, but the system is in maintenance and powered off temporarily.</p>
|
||||||
<p>Please come back later!</p>
|
<p>Please come back later!</p>
|
||||||
<p>Kind regards, <a href="https://tibo.depeuter.dev">Tibo De Peuter</a></p>
|
<p>Kind regards, <a href="https://tibo.depeuter.dev">Tibo De Peuter</a></p>
|
||||||
|
|
||||||
<div id="checkContainer"></div>
|
<div id="checkContainer"></div>
|
||||||
<img src="/assets/oh-no-kitten.jpg" alt="kitten holding paw to forehead"/>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<footer>
|
<img src="/assets/oh-no-kitten.jpg" alt="kitten holding paw to forehead"/>
|
||||||
<p>
|
|
||||||
Made with <span class="heart">♥</span>.
|
|
||||||
<a href="https://git.depeuter.dev/tdpeuter/down-website" about="source code of this webpage" class="hidden">Source code</a>
|
|
||||||
</p>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<script src="script.js"></script>
|
<script src="script.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
2332
package-lock.json
generated
2332
package-lock.json
generated
File diff suppressed because it is too large
Load diff
19
package.json
19
package.json
|
@ -1,19 +0,0 @@
|
||||||
{
|
|
||||||
"name": "down-message",
|
|
||||||
"version": "1.1.0",
|
|
||||||
"description": "Ultra simple website to tell people a service is down",
|
|
||||||
"main": "index.html",
|
|
||||||
"scripts": {
|
|
||||||
"start": "live-server --port=3000 .",
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://git.depeuter.dev/tdpeuter/down-message.git"
|
|
||||||
},
|
|
||||||
"author": "Tibo De Peuter <tibo@depeuter.dev>",
|
|
||||||
"license": "GPL-3.0-only",
|
|
||||||
"devDependencies": {
|
|
||||||
"live-server": "^1.2.2"
|
|
||||||
}
|
|
||||||
}
|
|
27
script.js
27
script.js
|
@ -1,18 +1,15 @@
|
||||||
async function websiteUp(url) {
|
async function websiteUp(url) {
|
||||||
// TODO Fix CORS
|
// TODO Fix CORS
|
||||||
try {
|
try {
|
||||||
const response = await fetch(url, { method: 'options' });
|
const response = await fetch(url, { method: 'head' });
|
||||||
return response.ok;
|
console.log(response);
|
||||||
|
return false;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`An error occurred while checking the URL '${url}': ${error.message}`);
|
console.error(`An error occurred while checking the URL '${url}': ${error.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function check(destination, container, dot, message, button) {
|
async function check(destination, container, dot, message, button) {
|
||||||
dot.className = 'dot orange';
|
|
||||||
message.textContent = 'Checking availability...';
|
|
||||||
button.style.visibility = 'hidden';
|
|
||||||
|
|
||||||
const destinationUp = await websiteUp(destination);
|
const destinationUp = await websiteUp(destination);
|
||||||
|
|
||||||
if (destinationUp) {
|
if (destinationUp) {
|
||||||
|
@ -37,8 +34,14 @@ async function check(destination, container, dot, message, button) {
|
||||||
|
|
||||||
function createCheckButton(destination) {
|
function createCheckButton(destination) {
|
||||||
const dot = document.createElement('span');
|
const dot = document.createElement('span');
|
||||||
|
dot.className = 'dot orange';
|
||||||
|
dot.id = 'checkDot';
|
||||||
|
|
||||||
const message = document.createElement('span');
|
const message = document.createElement('span');
|
||||||
|
message.textContent = 'Checking availability...';
|
||||||
|
|
||||||
const button = document.createElement('button');
|
const button = document.createElement('button');
|
||||||
|
button.style.visibility = 'hidden';
|
||||||
|
|
||||||
const container = document.getElementById('checkContainer');
|
const container = document.getElementById('checkContainer');
|
||||||
container.appendChild(dot);
|
container.appendChild(dot);
|
||||||
|
@ -48,23 +51,13 @@ function createCheckButton(destination) {
|
||||||
check(destination, container, dot, message, button);
|
check(destination, container, dot, message, button);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createTryAgainButton(destination) {
|
|
||||||
const button = document.createElement('button');
|
|
||||||
button.textContent = 'Try Again';
|
|
||||||
button.onclick = function () {
|
|
||||||
window.location.href = destination;
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById('checkContainer').appendChild(button);
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkDestination() {
|
function checkDestination() {
|
||||||
const url = window.location.search;
|
const url = window.location.search;
|
||||||
const searchParams = new URLSearchParams(url);
|
const searchParams = new URLSearchParams(url);
|
||||||
const destination = searchParams.get('destination');
|
const destination = searchParams.get('destination');
|
||||||
|
|
||||||
if (destination) {
|
if (destination) {
|
||||||
createTryAgainButton(destination);
|
createCheckButton(destination);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
62
style.css
62
style.css
|
@ -1,22 +1,3 @@
|
||||||
:root {
|
|
||||||
/* Support dark mode */
|
|
||||||
color-scheme: light dark;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 20px;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
|
||||||
opacity: 0.6;
|
|
||||||
font-size: small;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dot {
|
.dot {
|
||||||
width: 15px;
|
width: 15px;
|
||||||
height: 15px;
|
height: 15px;
|
||||||
|
@ -36,46 +17,3 @@ footer {
|
||||||
.dot.red {
|
.dot.red {
|
||||||
background-color: red;
|
background-color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
.heart {
|
|
||||||
color: #CD001A; /* Cherry red */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't let media go offscreen */
|
|
||||||
img,
|
|
||||||
picture,
|
|
||||||
video {
|
|
||||||
max-width: 100%;
|
|
||||||
padding: 2% 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Display the button in the center of small screens such as phones */
|
|
||||||
@media screen and (max-device-width: 1000px) {
|
|
||||||
#checkContainer {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hover animation for URLs */
|
|
||||||
a {
|
|
||||||
text-decoration: none;
|
|
||||||
color: inherit; /* Reset to default text color */
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
a::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
/* Height of the line */
|
|
||||||
bottom: -2px;
|
|
||||||
height: 2px;
|
|
||||||
left: 0;
|
|
||||||
width: 0;
|
|
||||||
background-color: orange;
|
|
||||||
transition: width 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover::before {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
Loading…
Reference in a new issue