Adding landing page
This commit is contained in:
@@ -0,0 +1,423 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ tenant_name }}</title>
|
||||
<style>
|
||||
:root {
|
||||
--primary: {{ tenant_primary_color }};
|
||||
--accent: {{ tenant_accent_color }};
|
||||
--bg: #0f172a;
|
||||
--surface: #1e293b;
|
||||
--surface2: #273449;
|
||||
--border: #334155;
|
||||
--text: #f1f5f9;
|
||||
--text-muted: #94a3b8;
|
||||
--radius: 10px;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* ── Header ── */
|
||||
header {
|
||||
background: var(--surface);
|
||||
border-bottom: 1px solid var(--border);
|
||||
padding: 0 2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
.brand {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
text-decoration: none;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
{% if tenant_logo_local_path %}
|
||||
.brand-logo {
|
||||
height: 36px;
|
||||
width: auto;
|
||||
}
|
||||
{% else %}
|
||||
.brand-icon {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
background: var(--primary);
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.25rem;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
.brand-name {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.domain-badge {
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-muted);
|
||||
background: var(--surface2);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
padding: 0.25rem 0.6rem;
|
||||
font-family: 'SF Mono', 'Fira Code', monospace;
|
||||
}
|
||||
|
||||
/* ── Hero ── */
|
||||
.hero {
|
||||
text-align: center;
|
||||
padding: 3.5rem 2rem 2.5rem;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
font-size: clamp(1.75rem, 4vw, 2.5rem);
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.03em;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.hero h1 span {
|
||||
background: linear-gradient(135deg, var(--primary), var(--accent));
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.hero p {
|
||||
color: var(--text-muted);
|
||||
font-size: 1.05rem;
|
||||
max-width: 520px;
|
||||
margin: 0 auto;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* ── Category sections ── */
|
||||
main {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 2rem 4rem;
|
||||
}
|
||||
|
||||
.category {
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
.category-title {
|
||||
font-size: 0.7rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 1rem;
|
||||
padding-bottom: 0.5rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
/* ── Service card ── */
|
||||
.card {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
padding: 1.25rem 1.5rem;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 1rem;
|
||||
text-decoration: none;
|
||||
color: var(--text);
|
||||
transition: border-color 0.15s, background 0.15s, transform 0.15s;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: var(--radius);
|
||||
background: linear-gradient(135deg, var(--primary), var(--accent));
|
||||
opacity: 0;
|
||||
transition: opacity 0.15s;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
border-color: var(--primary);
|
||||
background: var(--surface2);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.card:hover::after { opacity: 0.04; }
|
||||
|
||||
.card > * { position: relative; z-index: 1; }
|
||||
|
||||
.card-icon {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: 8px;
|
||||
background: var(--surface2);
|
||||
border: 1px solid var(--border);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
.card:hover .card-icon {
|
||||
background: var(--primary);
|
||||
border-color: var(--primary);
|
||||
}
|
||||
|
||||
.card-body { flex: 1; min-width: 0; }
|
||||
|
||||
.card-name {
|
||||
font-weight: 600;
|
||||
font-size: 0.95rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.card-desc {
|
||||
font-size: 0.82rem;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.5;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.card-url {
|
||||
font-size: 0.72rem;
|
||||
font-family: 'SF Mono', 'Fira Code', monospace;
|
||||
color: var(--primary);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* ── Footer ── */
|
||||
footer {
|
||||
border-top: 1px solid var(--border);
|
||||
text-align: center;
|
||||
padding: 1.5rem 2rem;
|
||||
color: var(--text-muted);
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
footer a { color: var(--primary); text-decoration: none; }
|
||||
footer a:hover { text-decoration: underline; }
|
||||
|
||||
@media (max-width: 600px) {
|
||||
header { padding: 0 1rem; }
|
||||
.hero { padding: 2rem 1rem 1.5rem; }
|
||||
main { padding: 0 1rem 3rem; }
|
||||
.grid { grid-template-columns: 1fr; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header>
|
||||
<a class="brand" href="https://{{ base_domain }}">
|
||||
{% if tenant_logo_local_path %}
|
||||
<img class="brand-logo" src="/logo" alt="{{ tenant_name }} logo">
|
||||
{% else %}
|
||||
<div class="brand-icon">{{ tenant_name[0] | upper }}</div>
|
||||
{% endif %}
|
||||
<span class="brand-name">{{ tenant_name }}</span>
|
||||
</a>
|
||||
<span class="domain-badge">{{ base_domain }}</span>
|
||||
</header>
|
||||
|
||||
<div class="hero">
|
||||
<h1>Your <span>self-hosted</span> workspace</h1>
|
||||
<p>All {{ tenant_name }} services in one place — private, secure, and fully under your control.</p>
|
||||
</div>
|
||||
|
||||
<main>
|
||||
|
||||
<!-- ── Collaboration ── -->
|
||||
<section class="category">
|
||||
<div class="category-title">Collaboration</div>
|
||||
<div class="grid">
|
||||
|
||||
<a class="card" href="https://cloud.{{ base_domain }}" target="_blank" rel="noopener">
|
||||
<div class="card-icon">☁</div>
|
||||
<div class="card-body">
|
||||
<div class="card-name">Nextcloud</div>
|
||||
<div class="card-desc">File storage, sharing, and collaboration suite. Sync files across devices and share with teammates.</div>
|
||||
<div class="card-url">cloud.{{ base_domain }}</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="card" href="https://chat.{{ base_domain }}" target="_blank" rel="noopener">
|
||||
<div class="card-icon">💬</div>
|
||||
<div class="card-body">
|
||||
<div class="card-name">Element / Matrix</div>
|
||||
<div class="card-desc">Encrypted team messaging and channels. Federated communication via the Matrix protocol.</div>
|
||||
<div class="card-url">chat.{{ base_domain }}</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="card" href="https://meet.{{ base_domain }}" target="_blank" rel="noopener">
|
||||
<div class="card-icon">🎦</div>
|
||||
<div class="card-body">
|
||||
<div class="card-name">Jitsi Meet</div>
|
||||
<div class="card-desc">Browser-based video conferencing. No account required — share a link to start a meeting instantly.</div>
|
||||
<div class="card-url">meet.{{ base_domain }}</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ── Email ── -->
|
||||
<section class="category">
|
||||
<div class="category-title">Email</div>
|
||||
<div class="grid">
|
||||
|
||||
<a class="card" href="https://webmail.{{ base_domain }}" target="_blank" rel="noopener">
|
||||
<div class="card-icon">✉</div>
|
||||
<div class="card-body">
|
||||
<div class="card-name">Roundcube Webmail</div>
|
||||
<div class="card-desc">Browser-based email client. Read, compose, and manage your @{{ base_domain }} inbox.</div>
|
||||
<div class="card-url">webmail.{{ base_domain }}</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="card" href="https://mail.{{ base_domain }}" target="_blank" rel="noopener">
|
||||
<div class="card-icon">📧</div>
|
||||
<div class="card-body">
|
||||
<div class="card-name">Stalwart Mail</div>
|
||||
<div class="card-desc">Mail server administration. Manage domains, mailboxes, aliases, and anti-spam settings.</div>
|
||||
<div class="card-url">mail.{{ base_domain }}</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ── Development ── -->
|
||||
<section class="category">
|
||||
<div class="category-title">Development</div>
|
||||
<div class="grid">
|
||||
|
||||
<a class="card" href="https://git.{{ base_domain }}" target="_blank" rel="noopener">
|
||||
<div class="card-icon">🌿</div>
|
||||
<div class="card-body">
|
||||
<div class="card-name">Forgejo</div>
|
||||
<div class="card-desc">Self-hosted Git platform. Manage repositories, review code, track issues, and run CI pipelines.</div>
|
||||
<div class="card-url">git.{{ base_domain }}</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="card" href="https://s3.{{ base_domain }}" target="_blank" rel="noopener">
|
||||
<div class="card-icon">💿</div>
|
||||
<div class="card-body">
|
||||
<div class="card-name">MinIO</div>
|
||||
<div class="card-desc">S3-compatible object storage. Store and serve large files, backups, and application assets.</div>
|
||||
<div class="card-url">s3.{{ base_domain }}</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ── Security & Access ── -->
|
||||
<section class="category">
|
||||
<div class="category-title">Security & Access</div>
|
||||
<div class="grid">
|
||||
|
||||
<a class="card" href="https://auth.{{ base_domain }}" target="_blank" rel="noopener">
|
||||
<div class="card-icon">🔒</div>
|
||||
<div class="card-body">
|
||||
<div class="card-name">Authentik</div>
|
||||
<div class="card-desc">Identity provider and SSO. Manage users, groups, and single sign-on across all services.</div>
|
||||
<div class="card-url">auth.{{ base_domain }}</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="card" href="https://vault.{{ base_domain }}" target="_blank" rel="noopener">
|
||||
<div class="card-icon">🔐</div>
|
||||
<div class="card-body">
|
||||
<div class="card-name">Vaultwarden</div>
|
||||
<div class="card-desc">Password manager compatible with Bitwarden clients. Store and autofill credentials securely.</div>
|
||||
<div class="card-url">vault.{{ base_domain }}</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="card" href="https://headscale.{{ base_domain }}" target="_blank" rel="noopener">
|
||||
<div class="card-icon">📡</div>
|
||||
<div class="card-body">
|
||||
<div class="card-name">Headscale</div>
|
||||
<div class="card-desc">WireGuard mesh VPN coordinator. Connect all your devices on a private, encrypted network.</div>
|
||||
<div class="card-url">headscale.{{ base_domain }}</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ── Operations ── -->
|
||||
<section class="category">
|
||||
<div class="category-title">Operations</div>
|
||||
<div class="grid">
|
||||
|
||||
<a class="card" href="https://logs.{{ base_domain }}" target="_blank" rel="noopener">
|
||||
<div class="card-icon">📊</div>
|
||||
<div class="card-body">
|
||||
<div class="card-name">Graylog</div>
|
||||
<div class="card-desc">Centralized log management. Search, analyze, and alert on logs from every service.</div>
|
||||
<div class="card-url">logs.{{ base_domain }}</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="card" href="https://wazuh.{{ base_domain }}" target="_blank" rel="noopener">
|
||||
<div class="card-icon">🛡</div>
|
||||
<div class="card-body">
|
||||
<div class="card-name">Wazuh</div>
|
||||
<div class="card-desc">Security information and event management (SIEM). Threat detection, compliance, and incident response.</div>
|
||||
<div class="card-url">wazuh.{{ base_domain }}</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="card" href="https://traefik.{{ base_domain }}" target="_blank" rel="noopener">
|
||||
<div class="card-icon">🔄</div>
|
||||
<div class="card-body">
|
||||
<div class="card-name">Traefik</div>
|
||||
<div class="card-desc">Reverse proxy and TLS dashboard. Monitor active routes, certificates, and service health.</div>
|
||||
<div class="card-url">traefik.{{ base_domain }}</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<p>Powered by <a href="https://git.{{ base_domain }}" target="_blank" rel="noopener">Sovereign</a> — {{ tenant_name }}</p>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user