rebrand: Klassenportal, domain info1.ifb.lol, server status
- Replace INFO1 brand with Klassenportal everywhere (titles, nav, emails, TOTP issuer, recovery codes) - Update domain from info1.simon0x.xyz to info1.ifb.lol - Remove E2EE claims (e2ee.js was deleted, claims were false) - Add GET /api/health endpoint (DB check + uptime) - Add live server status section to landing page - Fix README: domain, title, layout table
This commit is contained in:
+113
-24
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>INFO1 · Das Klassen-Cockpit</title>
|
||||
<meta name="description" content="INFO1 ist ein privates Klassenportal für die INFO1-Klasse. Stundenplan, Noten, Hausaufgaben, Klassen-Chat und mehr.">
|
||||
<title>Klassenportal · Das Klassen-Cockpit</title>
|
||||
<meta name="description" content="Privates Klassenportal für Schüler und Lehrer. Stundenplan, Noten, Hausaufgaben, Klassen-Chat und mehr.">
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap" rel="stylesheet">
|
||||
@@ -538,6 +538,35 @@ footer {
|
||||
flex-wrap: wrap; gap: 12px;
|
||||
}
|
||||
|
||||
/* ── STATUS ───────────────────── */
|
||||
.status-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 16px;
|
||||
max-width: 760px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.status-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
padding: 20px 24px;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 12px;
|
||||
}
|
||||
.status-dot {
|
||||
width: 10px; height: 10px;
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
background: var(--subtle);
|
||||
}
|
||||
.status-dot.ok { background: var(--green); box-shadow: 0 0 0 3px rgba(22,163,74,.15); }
|
||||
.status-dot.err { background: var(--red); box-shadow: 0 0 0 3px rgba(220,38,38,.15); }
|
||||
.status-label { font-size: 14px; font-weight: 600; color: var(--text); }
|
||||
.status-sub { font-size: 12px; color: var(--muted); margin-top: 1px; }
|
||||
@media (max-width: 600px) { .status-grid { grid-template-columns: 1fr; } }
|
||||
|
||||
/* ── REDACT ──────────────────── */
|
||||
.redact {
|
||||
display: inline-block;
|
||||
@@ -581,10 +610,10 @@ footer {
|
||||
<nav class="top">
|
||||
<div class="nav-inner">
|
||||
<a class="brand" href="/">
|
||||
<div class="brand-mark">i1</div>
|
||||
<div class="brand-mark">KP</div>
|
||||
<div class="brand-text">
|
||||
<span class="brand-sub">Klassenportal</span>
|
||||
<span class="brand-name">INFO1</span>
|
||||
<span class="brand-name">Klassenportal</span>
|
||||
</div>
|
||||
</a>
|
||||
<div class="nav-links">
|
||||
@@ -592,6 +621,7 @@ footer {
|
||||
<a href="#ueber">Für wen</a>
|
||||
<a href="#sicherheit">Sicherheit</a>
|
||||
<a href="#faq">FAQ</a>
|
||||
<a href="#status">Status</a>
|
||||
</div>
|
||||
<div class="nav-right">
|
||||
<button class="icon-btn" onclick="toggleDark()" title="Dark Mode" aria-label="Dark Mode"><i data-lucide="moon"></i></button>
|
||||
@@ -605,7 +635,7 @@ footer {
|
||||
<section class="hero">
|
||||
<div class="hero-inner">
|
||||
<div>
|
||||
<div class="eyebrow"><i data-lucide="sparkles"></i> Gemacht für die INFO1-Klasse</div>
|
||||
<div class="eyebrow"><i data-lucide="sparkles"></i> Gemacht für Schüler und Lehrer</div>
|
||||
<h1 class="hero-title">
|
||||
Dein Schulalltag, <span class="accent">an einem Ort.</span>
|
||||
</h1>
|
||||
@@ -624,7 +654,7 @@ footer {
|
||||
<div class="hero-trust">
|
||||
<span><i data-lucide="check"></i> Nur für IFB-Schüler</span>
|
||||
<span><i data-lucide="check"></i> 2-Faktor-Schutz</span>
|
||||
<span><i data-lucide="check"></i> Hetzner · Nürnberg</span>
|
||||
<span><i data-lucide="check"></i> Server in Deutschland</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -715,7 +745,7 @@ footer {
|
||||
<div class="feat">
|
||||
<div class="feat-icon"><i data-lucide="message-square"></i></div>
|
||||
<h3>Klassen-Chat</h3>
|
||||
<p>Ende-zu-Ende verschlüsselter Austausch mit der Klasse – direkt im Dashboard.</p>
|
||||
<p>Gemeinsamer Echtzeit-Chat mit der Klasse – direkt im Dashboard, kein WhatsApp nötig.</p>
|
||||
</div>
|
||||
<div class="feat">
|
||||
<div class="feat-icon"><i data-lucide="folder"></i></div>
|
||||
@@ -753,7 +783,7 @@ footer {
|
||||
<div class="sec-eyebrow">Für wen</div>
|
||||
<h2 class="sec-title">Zwei Perspektiven, ein System</h2>
|
||||
<p class="sec-lead">
|
||||
Ob du im Klassenzimmer sitzt oder davor stehst – INFO1 passt sich an deine Rolle an.
|
||||
Ob du im Klassenzimmer sitzt oder davor stehst – das Portal passt sich an deine Rolle an.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -766,7 +796,7 @@ footer {
|
||||
<li><i data-lucide="check"></i> Persönliches Dashboard mit deinem Stundenplan</li>
|
||||
<li><i data-lucide="check"></i> Noten-Übersicht mit automatischem Schnitt</li>
|
||||
<li><i data-lucide="check"></i> Hausaufgaben, To-Dos und Countdowns an einem Ort</li>
|
||||
<li><i data-lucide="check"></i> Verschlüsselter Klassen-Chat + Dateispeicher</li>
|
||||
<li><i data-lucide="check"></i> Klassen-Chat + persönlicher Dateispeicher</li>
|
||||
<li><i data-lucide="check"></i> Shared Kalender für Klausuren & Events</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -801,8 +831,8 @@ footer {
|
||||
<div class="sec-grid">
|
||||
<div class="sec-card">
|
||||
<i data-lucide="shield-check"></i>
|
||||
<h4>DSGVO & Hetzner DE</h4>
|
||||
<p>Server ausschließlich in Nürnberg. Keine Datenübertragung in Drittländer.</p>
|
||||
<h4>DSGVO & Deutschland</h4>
|
||||
<p>Server ausschließlich in Deutschland. Keine Datenübertragung in Drittländer.</p>
|
||||
</div>
|
||||
<div class="sec-card">
|
||||
<i data-lucide="key-round"></i>
|
||||
@@ -810,9 +840,9 @@ footer {
|
||||
<p>Optionaler TOTP-Schutz per Authenticator-App für deinen Account.</p>
|
||||
</div>
|
||||
<div class="sec-card">
|
||||
<i data-lucide="lock"></i>
|
||||
<h4>Ende-zu-Ende-Chat</h4>
|
||||
<p>Chat-Nachrichten werden im Browser verschlüsselt – der Server liest nicht mit.</p>
|
||||
<i data-lucide="zap-off"></i>
|
||||
<h4>Kein Tracking</h4>
|
||||
<p>Keine Werbung, keine Analytics, keine Weitergabe. Nur die Daten, die der Betrieb braucht.</p>
|
||||
</div>
|
||||
<div class="sec-card">
|
||||
<i data-lucide="mail-check"></i>
|
||||
@@ -835,7 +865,7 @@ footer {
|
||||
<details class="faq-item">
|
||||
<summary>Was kostet die Nutzung?</summary>
|
||||
<div class="faq-body">
|
||||
Nichts. INFO1 ist ein privates Projekt für die Klasse und kostet die Nutzer keinen Cent.
|
||||
Nichts. Das Klassenportal ist ein privates Projekt und kostet die Nutzer keinen Cent.
|
||||
</div>
|
||||
</details>
|
||||
<details class="faq-item">
|
||||
@@ -848,15 +878,14 @@ footer {
|
||||
<details class="faq-item">
|
||||
<summary>Wo liegen meine Daten?</summary>
|
||||
<div class="faq-body">
|
||||
Auf einem Hetzner-Server in Nürnberg, Deutschland. Es findet keine Übertragung in Drittländer statt.
|
||||
Auf einem Server in Deutschland. Es findet keine Übertragung in Drittländer statt.
|
||||
Details in der <a href="/datenschutz" style="color:var(--blue);">Datenschutzerklärung</a>.
|
||||
</div>
|
||||
</details>
|
||||
<details class="faq-item">
|
||||
<summary>Kann der Admin meinen Chat lesen?</summary>
|
||||
<div class="faq-body">
|
||||
Nein. Chat-Nachrichten werden im Browser mit einem Klassen-Schlüssel verschlüsselt, bevor sie den Server erreichen.
|
||||
Auf dem Server liegen nur Chiffre-Texte.
|
||||
Ja. Chat-Nachrichten sind für den Admin einsehbar.
|
||||
</div>
|
||||
</details>
|
||||
<details class="faq-item">
|
||||
@@ -867,7 +896,7 @@ footer {
|
||||
</div>
|
||||
</details>
|
||||
<details class="faq-item">
|
||||
<summary>Läuft INFO1 auch auf dem Handy?</summary>
|
||||
<summary>Läuft das Klassenportal auch auf dem Handy?</summary>
|
||||
<div class="faq-body">
|
||||
Ja. Das Dashboard ist voll responsive und funktioniert auf Smartphone, Tablet und Desktop gleich gut.
|
||||
</div>
|
||||
@@ -876,6 +905,39 @@ footer {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- STATUS -->
|
||||
<section id="status">
|
||||
<div class="section-inner">
|
||||
<div class="sec-head">
|
||||
<div class="sec-eyebrow">Systemstatus</div>
|
||||
<h2 class="sec-title">Alles im grünen Bereich</h2>
|
||||
</div>
|
||||
<div class="status-grid">
|
||||
<div class="status-card">
|
||||
<div class="status-dot" id="st-api"></div>
|
||||
<div>
|
||||
<div class="status-label">API</div>
|
||||
<div class="status-sub" id="st-api-sub">Wird geprüft…</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="status-card">
|
||||
<div class="status-dot" id="st-db"></div>
|
||||
<div>
|
||||
<div class="status-label">Datenbank</div>
|
||||
<div class="status-sub" id="st-db-sub">Wird geprüft…</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="status-card">
|
||||
<div class="status-dot" id="st-up"></div>
|
||||
<div>
|
||||
<div class="status-label">Uptime</div>
|
||||
<div class="status-sub" id="st-up-sub">Wird geprüft…</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- CTA -->
|
||||
<section>
|
||||
<div class="cta-band">
|
||||
@@ -893,13 +955,13 @@ footer {
|
||||
<div class="foot-inner">
|
||||
<div class="foot-about">
|
||||
<a class="brand" href="/">
|
||||
<div class="brand-mark">i1</div>
|
||||
<div class="brand-mark">KP</div>
|
||||
<div class="brand-text">
|
||||
<span class="brand-sub">Klassenportal</span>
|
||||
<span class="brand-name">INFO1</span>
|
||||
<span class="brand-name">Klassenportal</span>
|
||||
</div>
|
||||
</a>
|
||||
<p>Privates Klassenportal für die INFO1-Klasse. Kein offizielles Angebot einer Schule oder eines Trägers. Daten gehostet in Deutschland.</p>
|
||||
<p>Privates Klassenportal für Schüler und Lehrer. Kein offizielles Angebot einer Schule oder eines Trägers. Daten gehostet in Deutschland.</p>
|
||||
</div>
|
||||
<div class="foot-col">
|
||||
<h5>Produkt</h5>
|
||||
@@ -927,8 +989,8 @@ footer {
|
||||
</div>
|
||||
</div>
|
||||
<div class="foot-bottom">
|
||||
<span>© <span id="y"></span> INFO1 · Privates Klassenportal (inoffiziell)</span>
|
||||
<span>Daten auf Hetzner, Nürnberg · EU-DSGVO konform</span>
|
||||
<span>© <span id="y"></span> Klassenportal · Privat & inoffiziell</span>
|
||||
<span>Daten in Deutschland · EU-DSGVO konform</span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -942,6 +1004,33 @@ footer {
|
||||
try { if (localStorage.getItem('dark') === '1') document.body.classList.add('dark'); } catch {}
|
||||
|
||||
lucide.createIcons();
|
||||
|
||||
(async function checkStatus() {
|
||||
function fmt(s) {
|
||||
if (s < 60) return s + 's';
|
||||
if (s < 3600) return Math.floor(s / 60) + 'm';
|
||||
if (s < 86400) return Math.floor(s / 3600) + 'h';
|
||||
return Math.floor(s / 86400) + 'd';
|
||||
}
|
||||
try {
|
||||
const r = await fetch('/api/health');
|
||||
const d = await r.json();
|
||||
const ok = d.ok === true;
|
||||
document.getElementById('st-api').className = 'status-dot ' + (ok ? 'ok' : 'err');
|
||||
document.getElementById('st-api-sub').textContent = ok ? 'Online' : 'Fehler';
|
||||
document.getElementById('st-db').className = 'status-dot ' + (ok ? 'ok' : 'err');
|
||||
document.getElementById('st-db-sub').textContent = ok ? 'Online' : 'Nicht erreichbar';
|
||||
document.getElementById('st-up').className = 'status-dot ok';
|
||||
document.getElementById('st-up-sub').textContent = ok ? fmt(d.uptime) : '–';
|
||||
} catch {
|
||||
['st-api','st-db','st-up'].forEach(id => {
|
||||
document.getElementById(id).className = 'status-dot err';
|
||||
});
|
||||
document.getElementById('st-api-sub').textContent = 'Nicht erreichbar';
|
||||
document.getElementById('st-db-sub').textContent = '–';
|
||||
document.getElementById('st-up-sub').textContent = '–';
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user