mirror of
https://github.com/ION606/static-site-hosting.git
synced 2026-05-14 22:16:54 +00:00
name change
This commit is contained in:
@@ -1,15 +1,18 @@
|
|||||||
# ION Static Site Hosting
|
# TinySite.cloud Hosting
|
||||||
|
|
||||||
ION Static Site Hosting is a lightweight Python application designed to serve static websites effortlessly. Built with Flask, it allows developers to deploy HTML, CSS, JavaScript, and image files quickly, making it ideal for personal projects, documentation, or simple web pages.
|
TinySite.cloud Hosting is a lightweight Python application designed to serve static websites effortlessly. Built with Flask, it allows developers to deploy HTML, CSS, JavaScript, and image files quickly, making it ideal for personal projects, documentation, or simple web pages.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
- Easy usage
|
|
||||||
- Sleek and simple UI
|
- Easy usage
|
||||||
- Syntax highlighting/In-browser code editor
|
- Sleek and simple UI
|
||||||
- Default dark mode!!!
|
- Syntax highlighting/In-browser code editor
|
||||||
|
- Default dark mode!!!
|
||||||
|
|
||||||
## Self-Hosting?
|
## Self-Hosting?
|
||||||
|
|
||||||
Just clone the repo, then use the following to get started:
|
Just clone the repo, then use the following to get started:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python -m venv .venv
|
python -m venv .venv
|
||||||
# Activate the env (use .venv/bin/activate.fish for fish)
|
# Activate the env (use .venv/bin/activate.fish for fish)
|
||||||
@@ -17,6 +20,7 @@ source .venv/bin/activate
|
|||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
python app.py
|
python app.py
|
||||||
```
|
```
|
||||||
|
|
||||||
And that's it! The app should be available at http://localhost:5121
|
And that's it! The app should be available at http://localhost:5121
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|||||||
+124
-102
@@ -1,117 +1,139 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
content="TinySite.cloud Hosting offers effortless hosting and sharing of static sites with instant deployment, dark mode interface, and secure, private data handling!" />
|
||||||
|
<meta
|
||||||
|
name="keywords"
|
||||||
|
content="static site hosting, instant deployment, dark mode, secure hosting, private data, file management, blazing fast" />
|
||||||
|
<meta name="author" content="ION606" />
|
||||||
|
<meta property="og:title" content="TinySite.cloud" />
|
||||||
|
<meta
|
||||||
|
property="og:description"
|
||||||
|
content="Host and share your static sites effortlessly with TinySite.cloud Hosting. Enjoy instant deployment, a sleek dark mode interface, and secure, private data handling!" />
|
||||||
|
<meta
|
||||||
|
property="og:image"
|
||||||
|
content="{{ url_for('static', filename='hosting.png') }}" />
|
||||||
|
<meta property="og:url" content="https://{{ SERVERNAME }}/" />
|
||||||
|
<meta
|
||||||
|
name="twitter:card"
|
||||||
|
content="{{ url_for('static', filename='hosting.png') }}" />
|
||||||
|
<meta name="twitter:title" content="TinySite.cloud" />
|
||||||
|
<meta
|
||||||
|
name="twitter:description"
|
||||||
|
content="Host and share your static sites effortlessly with TinySite.cloud Hosting. Enjoy instant deployment, a sleek dark mode interface, and secure, private data handling!" />
|
||||||
|
<meta
|
||||||
|
name="twitter:image"
|
||||||
|
content="{{ url_for('static', filename='hosting.png') }}" />
|
||||||
|
|
||||||
<head>
|
<title>TinySite.cloud - {% block title %}{% endblock %}</title>
|
||||||
<meta charset="UTF-8">
|
<link
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
rel="stylesheet"
|
||||||
<meta name="description"
|
href="{{ url_for('static', filename='styles.css') }}"
|
||||||
content="ION Static Site Hosting offers effortless hosting and sharing of static sites with instant deployment, dark mode interface, and secure, private data handling!">
|
id="theme-style" />
|
||||||
<meta name="keywords"
|
<link
|
||||||
content="static site hosting, instant deployment, dark mode, secure hosting, private data, file management, blazing fast">
|
rel="icon"
|
||||||
<meta name="author" content="ION606">
|
href="{{ url_for('static', filename='favicon.ico') }}" />
|
||||||
<meta property="og:title" content="ION Static Site Hosting">
|
|
||||||
<meta property="og:description"
|
|
||||||
content="Host and share your static sites effortlessly with ION Static Site Hosting. Enjoy instant deployment, a sleek dark mode interface, and secure, private data handling!">
|
|
||||||
<meta property="og:image" content="{{ url_for('static', filename='hosting.png') }}">
|
|
||||||
<meta property="og:url" content="https://{{ SERVERNAME }}/">
|
|
||||||
<meta name="twitter:card" content="{{ url_for('static', filename='hosting.png') }}">
|
|
||||||
<meta name="twitter:title" content="ION Static Site Hosting">
|
|
||||||
<meta name="twitter:description"
|
|
||||||
content="Host and share your static sites effortlessly with ION Static Site Hosting. Enjoy instant deployment, a sleek dark mode interface, and secure, private data handling!">
|
|
||||||
<meta name="twitter:image" content="{{ url_for('static', filename='hosting.png') }}">
|
|
||||||
|
|
||||||
<title>ION Static Site Hosting - {% block title %}{% endblock %}</title>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}" id="theme-style">
|
<script>
|
||||||
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const themeToggle = document.querySelector("#theme-toggle");
|
||||||
|
const body = document.body;
|
||||||
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
|
// get saved theme from localStorage
|
||||||
<script>
|
const savedTheme = localStorage.getItem("theme") || "dark";
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
body.setAttribute("data-theme", savedTheme);
|
||||||
const themeToggle = document.querySelector('#theme-toggle');
|
|
||||||
const body = document.body;
|
|
||||||
|
|
||||||
// get saved theme from localStorage
|
if (!savedTheme) localStorage.setItem("theme", savedTheme);
|
||||||
const savedTheme = localStorage.getItem('theme') || 'dark';
|
|
||||||
body.setAttribute('data-theme', savedTheme);
|
|
||||||
|
|
||||||
if (!savedTheme) localStorage.setItem('theme', savedTheme);
|
// set initial button text
|
||||||
|
themeToggle.textContent =
|
||||||
|
savedTheme === "dark" ? "light mode" : "dark mode";
|
||||||
|
|
||||||
// set initial button text
|
themeToggle.addEventListener("click", () => {
|
||||||
themeToggle.textContent = savedTheme === 'dark' ? 'light mode' : 'dark mode';
|
const isDark = body.getAttribute("data-theme") === "dark";
|
||||||
|
body.setAttribute("data-theme", isDark ? "light" : "dark");
|
||||||
themeToggle.addEventListener('click', () => {
|
localStorage.setItem("theme", isDark ? "light" : "dark");
|
||||||
const isDark = body.getAttribute('data-theme') === 'dark';
|
themeToggle.textContent = isDark
|
||||||
body.setAttribute('data-theme', isDark ? 'light' : 'dark');
|
? "dark mode"
|
||||||
localStorage.setItem('theme', isDark ? 'light' : 'dark');
|
: "light mode";
|
||||||
themeToggle.textContent = isDark ? 'dark mode' : 'light mode';
|
});
|
||||||
});
|
});
|
||||||
});
|
</script>
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.navbar-toggle {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.navbar-toggle {
|
.navbar-toggle {
|
||||||
display: block;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
@media (max-width: 768px) {
|
||||||
<nav class="navbar">
|
.navbar-toggle {
|
||||||
<div class="container">
|
display: block;
|
||||||
<a href="{{ url_for('main.home', _external=True) }}">Home</a>
|
|
||||||
<button id="nav-toggle" class="navbar-toggle" aria-label="menu">☰</button>
|
|
||||||
<div id="navbar-links" class="navbar-links">
|
|
||||||
{% if current_user.is_authenticated %}
|
|
||||||
<a href="{{ url_for('main.dashboard', _external=True) }}">Dashboard</a>
|
|
||||||
<a href="{{ url_for('main.logout', _external=True) }}">Logout</a>
|
|
||||||
{% else %}
|
|
||||||
<a href="{{ url_for('main.login', _external=True) }}">Login</a>
|
|
||||||
<a href="{{ url_for('main.register', _external=True) }}">Register</a>
|
|
||||||
{% endif %}
|
|
||||||
<button id="theme-toggle" class="btn">toggle dark mode</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
|
||||||
{% if messages %}
|
|
||||||
{% for category, message in messages %}
|
|
||||||
<div class="flash-message flash-{{ category }}">
|
|
||||||
{{ message }}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
{% endwith %}
|
|
||||||
|
|
||||||
{% block content %}{% endblock %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
const navToggle = document.querySelector('#nav-toggle');
|
|
||||||
const navbarLinks = document.querySelector('#navbar-links');
|
|
||||||
const navbar = document.querySelector('.navbar');
|
|
||||||
|
|
||||||
navToggle.addEventListener('click', () => {
|
|
||||||
navbarLinks.classList.toggle('active');
|
|
||||||
navToggle.classList.toggle('active');
|
|
||||||
});
|
|
||||||
|
|
||||||
document.addEventListener('click', (e) => {
|
|
||||||
if (!navbar.contains(e.target)) {
|
|
||||||
navbarLinks.classList.remove('active');
|
|
||||||
navToggle.classList.remove('active');
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
});
|
</style>
|
||||||
</script>
|
</head>
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
<body>
|
||||||
|
<nav class="navbar">
|
||||||
|
<div class="container">
|
||||||
|
<a href="{{ url_for('main.home', _external=True) }}">Home</a>
|
||||||
|
<button id="nav-toggle" class="navbar-toggle" aria-label="menu">
|
||||||
|
☰
|
||||||
|
</button>
|
||||||
|
<div id="navbar-links" class="navbar-links">
|
||||||
|
{% if current_user.is_authenticated %}
|
||||||
|
<a href="{{ url_for('main.dashboard', _external=True) }}"
|
||||||
|
>Dashboard</a
|
||||||
|
>
|
||||||
|
<a href="{{ url_for('main.logout', _external=True) }}"
|
||||||
|
>Logout</a
|
||||||
|
>
|
||||||
|
{% else %}
|
||||||
|
<a href="{{ url_for('main.login', _external=True) }}"
|
||||||
|
>Login</a
|
||||||
|
>
|
||||||
|
<a href="{{ url_for('main.register', _external=True) }}"
|
||||||
|
>Register</a
|
||||||
|
>
|
||||||
|
{% endif %}
|
||||||
|
<button id="theme-toggle" class="btn">
|
||||||
|
toggle dark mode
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
{% with messages = get_flashed_messages(with_categories=true) %} {%
|
||||||
|
if messages %} {% for category, message in messages %}
|
||||||
|
<div class="flash-message flash-{{ category }}">{{ message }}</div>
|
||||||
|
{% endfor %} {% endif %} {% endwith %} {% block content %}{%
|
||||||
|
endblock %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const navToggle = document.querySelector("#nav-toggle");
|
||||||
|
const navbarLinks = document.querySelector("#navbar-links");
|
||||||
|
const navbar = document.querySelector(".navbar");
|
||||||
|
|
||||||
|
navToggle.addEventListener("click", () => {
|
||||||
|
navbarLinks.classList.toggle("active");
|
||||||
|
navToggle.classList.toggle("active");
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener("click", (e) => {
|
||||||
|
if (!navbar.contains(e.target)) {
|
||||||
|
navbarLinks.classList.remove("active");
|
||||||
|
navToggle.classList.remove("active");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|||||||
+19
-18
@@ -1,6 +1,4 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %} {% block content %}
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<div class="floating-balls"></div>
|
<div class="floating-balls"></div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -13,12 +11,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: 'Arial', sans-serif;
|
font-family: "Arial", sans-serif;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
background-color: var(--bg-color);
|
background-color: var(--bg-color);
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
transition: background-color var(--transition-speed) ease, color var(--transition-speed) ease;
|
transition: background-color var(--transition-speed) ease,
|
||||||
|
color var(--transition-speed) ease;
|
||||||
animation: fadeIn var(--fade-duration) ease-out;
|
animation: fadeIn var(--fade-duration) ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +61,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes bounce {
|
@keyframes bounce {
|
||||||
|
|
||||||
0%,
|
0%,
|
||||||
20%,
|
20%,
|
||||||
50%,
|
50%,
|
||||||
@@ -199,14 +197,16 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
<h1>🚀 ION Static Site Hosting</h1>
|
<h1>🚀 TinySite.cloud</h1>
|
||||||
<p>Host and share your static sites effortlessly.</p>
|
<p>Host and share your static sites effortlessly.</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="main-container">
|
<div class="main-container">
|
||||||
<h2>Why Choose Us?</h2>
|
<h2>Why Choose Us?</h2>
|
||||||
<p>Whether you’re a developer, designer, or just need to showcase your work, we make it easy to host and share
|
<p>
|
||||||
static sites.</p>
|
Whether you’re a developer, designer, or just need to showcase your
|
||||||
|
work, we make it easy to host and share static sites.
|
||||||
|
</p>
|
||||||
|
|
||||||
<div class="feature-list">
|
<div class="feature-list">
|
||||||
<div class="feature">
|
<div class="feature">
|
||||||
@@ -247,10 +247,10 @@
|
|||||||
|
|
||||||
<!-- JavaScript to create balls and add "pop" effects -->
|
<!-- JavaScript to create balls and add "pop" effects -->
|
||||||
<script>
|
<script>
|
||||||
const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", async () => {
|
document.addEventListener("DOMContentLoaded", async () => {
|
||||||
const container = document.querySelector('.floating-balls');
|
const container = document.querySelector(".floating-balls");
|
||||||
|
|
||||||
// Generate a random number of balls between 10 and 30
|
// Generate a random number of balls between 10 and 30
|
||||||
const ballCount = Math.floor(Math.random() * 21) + 10;
|
const ballCount = Math.floor(Math.random() * 21) + 10;
|
||||||
@@ -258,14 +258,14 @@
|
|||||||
const ball = document.createElement("div");
|
const ball = document.createElement("div");
|
||||||
ball.classList.add("floating-ball");
|
ball.classList.add("floating-ball");
|
||||||
|
|
||||||
await wait(Math.random() * 2000)
|
await wait(Math.random() * 2000);
|
||||||
|
|
||||||
// Randomize properties
|
// Randomize properties
|
||||||
const size = 30 + Math.random() * 40;
|
const size = 30 + Math.random() * 40;
|
||||||
ball.style.width = size + "px";
|
ball.style.width = size + "px";
|
||||||
ball.style.height = size + "px";
|
ball.style.height = size + "px";
|
||||||
ball.style.left = Math.random() * 100 + "%";
|
ball.style.left = Math.random() * 100 + "%";
|
||||||
ball.style.animationDuration = (10 + Math.random() * 10) + "s";
|
ball.style.animationDuration = 10 + Math.random() * 10 + "s";
|
||||||
ball.style.animationDelay = Math.random() * 5 + "s";
|
ball.style.animationDelay = Math.random() * 5 + "s";
|
||||||
|
|
||||||
container.appendChild(ball);
|
container.appendChild(ball);
|
||||||
@@ -273,16 +273,17 @@
|
|||||||
|
|
||||||
// random pop every 2 seconds
|
// random pop every 2 seconds
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
const balls = document.querySelectorAll('.floating-ball');
|
const balls = document.querySelectorAll(".floating-ball");
|
||||||
if (balls.length) {
|
if (balls.length) {
|
||||||
const randomBall = balls[Math.floor(Math.random() * balls.length)];
|
const randomBall =
|
||||||
randomBall.classList.add('pop');
|
balls[Math.floor(Math.random() * balls.length)];
|
||||||
|
randomBall.classList.add("pop");
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
randomBall.classList.remove('pop');
|
randomBall.classList.remove("pop");
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
}, 2000);
|
}, 2000);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
Reference in New Issue
Block a user