Homepage: logo hero, arrow-key gallery, full-size screenshots, phone beside Security
The logo and name lead the page with the tagline as a small bold title above the lead. Screenshots are stored at full resolution, the gallery has a nav link and steps through every screenshot with the arrow keys or on-screen arrows, the phone shot moves beside the Security and privacy list, a community channel shot sits under the feature list, features get real bullets, and the wording moves backups to Extras and mentions theme effects.
No files matched your search
@@ -19,6 +19,11 @@ Format follows [Keep a Changelog](https://keepachangelog.com/). Haven uses [Sema
|
||||
people who never will. It is per browser, and the fold survives channel
|
||||
switches and reloads. Requested by @quakeman00.
|
||||
|
||||
### Changed
|
||||
- **Homepage.** The logo leads the page, the screenshots are full size with a
|
||||
Gallery you can step through with the arrow keys, the phone shot sits beside
|
||||
Security and privacy, and a community channel shot follows the feature list.
|
||||
|
||||
### Fixed
|
||||
- **CRT text reads bigger (#5606).** The theme's VT323 face is scaled up a
|
||||
further notch, so sub-channel names and other fine print no longer read a
|
||||
|
||||
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 155 KiB |
|
After Width: | Height: | Size: 293 KiB |
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 330 KiB |
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 536 KiB |
@@ -7,11 +7,11 @@
|
||||
<meta property="og:description" content="Haven is a free, open source alternative to Discord that you host on your own computer. Channels, voice, screen sharing, threads and encrypted DMs. Friends join with a link, the desktop app or the Android app.">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="https://ancsemi.github.io/Haven/">
|
||||
<meta property="og:image" content="https://ancsemi.github.io/Haven/img/haven-4-5-default.jpg">
|
||||
<meta property="og:image" content="https://ancsemi.github.io/Haven/img/haven-4-6-default.jpg">
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:title" content="Haven, a chat server you run yourself">
|
||||
<meta name="twitter:description" content="Haven is a free, open source alternative to Discord that you host on your own computer. Channels, voice, screen sharing, threads and encrypted DMs. Friends join with a link, the desktop app or the Android app.">
|
||||
<meta name="twitter:image" content="https://ancsemi.github.io/Haven/img/haven-4-5-default.jpg">
|
||||
<meta name="twitter:image" content="https://ancsemi.github.io/Haven/img/haven-4-6-default.jpg">
|
||||
<meta name="twitter:site" content="@ancsemi">
|
||||
<link rel="canonical" href="https://ancsemi.github.io/Haven/">
|
||||
<meta name="theme-color" content="#F6F5F9">
|
||||
@@ -135,7 +135,10 @@
|
||||
/* ── Hero ────────────────────────────────────────── */
|
||||
.hero { padding-top: clamp(40px, 6vw, 72px); }
|
||||
.hero-grid { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); gap: clamp(28px, 5vw, 64px); align-items: start; }
|
||||
.hero .lead { font-size: 20px; line-height: 1.5; margin-top: 22px; max-width: 34em; }
|
||||
.hero-brand { display: inline-flex; align-items: center; gap: 0.32em; color: var(--ink); font-weight: 600; font-size: clamp(48px, 7vw, 76px); letter-spacing: 0.01em; line-height: 1; }
|
||||
.hero-brand svg { width: 1.05em; height: 1.05em; flex: none; }
|
||||
.hero-title { font-size: clamp(20px, 2.4vw, 25px); font-weight: 700; letter-spacing: -0.01em; margin-top: 30px; }
|
||||
.hero .lead { font-size: 20px; line-height: 1.5; margin-top: 10px; max-width: 34em; }
|
||||
.actions { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; margin-top: 30px; }
|
||||
.btn { display: inline-flex; align-items: center; gap: 8px; padding: 11px 18px; border-radius: 4px; font-weight: 600; font-size: 16px; text-decoration: none; border: 1px solid transparent; line-height: 1.2; }
|
||||
.btn-primary { background: var(--accent); color: var(--accent-ink); }
|
||||
@@ -166,8 +169,9 @@
|
||||
.cols > div:first-child { padding-left: 0; border-left: 0; }
|
||||
.cols > div:last-child { padding-right: 0; }
|
||||
.cols h3 { margin-bottom: 10px; padding-bottom: 8px; border-bottom: 1px solid var(--rule); }
|
||||
.cols ul { list-style: none; padding: 0; }
|
||||
.cols li { padding-left: 0; font-size: 16px; }
|
||||
.cols ul { list-style: disc; padding-left: 1.1em; }
|
||||
.cols li { font-size: 16px; }
|
||||
.cols li::marker { color: var(--accent); }
|
||||
.cols li + li { margin-top: 0.5em; }
|
||||
|
||||
/* ── Steps ───────────────────────────────────────── */
|
||||
@@ -205,6 +209,11 @@
|
||||
.lightbox { position: fixed; inset: 0; z-index: 50; background: rgba(10, 8, 16, 0.92); display: flex; align-items: center; justify-content: center; padding: 24px; cursor: zoom-out; }
|
||||
.lightbox[hidden] { display: none; }
|
||||
.lightbox img { max-width: 100%; max-height: 100%; border-radius: 6px; box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5); }
|
||||
.lb-nav { position: absolute; top: 50%; transform: translateY(-50%); width: 44px; height: 44px; border: 0; border-radius: 50%; background: rgba(255, 255, 255, 0.14); color: #fff; font-size: 30px; line-height: 1; cursor: pointer; display: grid; place-items: center; padding: 0 0 4px; }
|
||||
.lb-nav:hover { background: rgba(255, 255, 255, 0.26); }
|
||||
.lb-prev { left: 18px; }
|
||||
.lb-next { right: 18px; }
|
||||
@media (max-width: 700px) { .lb-nav { width: 36px; height: 36px; font-size: 24px; } .lb-prev { left: 8px; } .lb-next { right: 8px; } }
|
||||
|
||||
/* ── Facts ───────────────────────────────────────── */
|
||||
.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 0; border-top: 1px solid var(--rule-strong); border-bottom: 1px solid var(--rule-strong); }
|
||||
@@ -263,6 +272,7 @@
|
||||
<a href="#compare">Compare</a>
|
||||
<a href="#setup">Setup</a>
|
||||
<a href="#security">Security</a>
|
||||
<a href="#screenshots">Gallery</a>
|
||||
<a href="#download">Download</a>
|
||||
<a href="https://github.com/ancsemi/Haven">GitHub</a>
|
||||
<a class="btn-try" id="try-now" href="#top">Try it now</a>
|
||||
@@ -275,7 +285,11 @@
|
||||
<div class="wrap">
|
||||
<div class="hero-grid">
|
||||
<div>
|
||||
<h1>A chat server you run yourself.</h1>
|
||||
<div class="hero-brand" aria-hidden="true">
|
||||
<svg viewBox="0 0 100 100"><polygon points="50,3 93,28 93,72 50,97 7,72 7,28" fill="none" stroke="currentColor" stroke-width="8" stroke-linejoin="round"/></svg>
|
||||
Haven
|
||||
</div>
|
||||
<h1 class="hero-title">A chat server you run yourself.</h1>
|
||||
<p class="lead">Haven is a free, open source alternative to Discord. It runs on your own computer, your friends join with a link, and there's no company in the middle.</p>
|
||||
<div class="actions">
|
||||
<a class="btn btn-primary" href="https://github.com/ancsemi/Haven/archive/refs/tags/v4.6.0.zip">Download Haven <span class="ver">4.6.0</span></a>
|
||||
@@ -300,15 +314,14 @@
|
||||
</div>
|
||||
</div>
|
||||
<figure class="shot">
|
||||
<img class="zoomable" src="img/haven-4-6-default.jpg" width="1600" height="843" alt="Haven's default theme: channels and DMs on the left, the member list on the right">
|
||||
<img class="zoomable" src="img/haven-4-6-default.jpg" width="1918" height="1010" alt="Haven's default theme: channels and DMs on the left, the member list on the right">
|
||||
</figure>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="about">
|
||||
<div class="wrap">
|
||||
<div class="split">
|
||||
<div class="prose">
|
||||
<div class="prose">
|
||||
<div class="section-head">
|
||||
<h2>About</h2>
|
||||
</div>
|
||||
@@ -316,11 +329,6 @@
|
||||
<p>There's no company in the middle. No account with us, no email or phone number, and nothing to pay for. Your messages, files and voice calls stay on your own server.</p>
|
||||
<p>Haven has been in development since February 2026. It's a spare-time project and it'll always be free.</p>
|
||||
<p>Many helpful people with a shared passion for free, unfiltered and private chat have come together to improve it. Every change is public, with a <a href="https://github.com/ancsemi/Haven/blob/main/CHANGELOG.md">changelog</a> updated every release.</p>
|
||||
</div>
|
||||
<figure class="fig">
|
||||
<img class="zoomable" src="img/haven-phone-welcome.jpg" width="480" height="1040" alt="Haven's welcome screen in a phone browser">
|
||||
<figcaption>Joining from a phone browser. No app needed.</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -354,10 +362,9 @@
|
||||
<div>
|
||||
<h3>Customization</h3>
|
||||
<ul>
|
||||
<li>26 themes, or write your own CSS</li>
|
||||
<li>26 themes with customizable effects, or write your own CSS</li>
|
||||
<li>Bots and webhooks</li>
|
||||
<li>Sign in with your own identity provider</li>
|
||||
<li>Backups and updates from the settings page</li>
|
||||
<li>Guest access, invite links and channel codes</li>
|
||||
<li>Available in 8 languages</li>
|
||||
</ul>
|
||||
@@ -368,9 +375,13 @@
|
||||
<li>Rich Presence: show what you're playing or listening to</li>
|
||||
<li>Built-in games with leaderboards</li>
|
||||
<li>Flash games, through Ruffle</li>
|
||||
<li>Backups and updates from the settings page</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<figure class="shot">
|
||||
<img class="zoomable" src="img/haven-features.jpg" width="1915" height="1005" alt="A community channel in the Braid theme with the member list open" loading="lazy">
|
||||
</figure>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -427,7 +438,8 @@
|
||||
<h2>Security and privacy</h2>
|
||||
<p>How it actually works.</p>
|
||||
</div>
|
||||
<div class="prose">
|
||||
<div class="split">
|
||||
<div class="prose">
|
||||
<ul>
|
||||
<li><strong>Your data lives on the computer running the server,</strong> in one folder. Back it up, move it or delete it whenever you want.</li>
|
||||
<li><strong>Direct messages are end-to-end encrypted.</strong> The server stores them but can't read them, and neither can the admin.</li>
|
||||
@@ -436,6 +448,13 @@
|
||||
<li><strong>No telemetry.</strong> The server doesn't send usage data or crash reports anywhere.</li>
|
||||
<li><strong>There's no central Haven server and no Haven account.</strong> Nothing to leak.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<figure class="fig">
|
||||
<img class="zoomable" src="img/haven-phone-welcome.jpg" width="480" height="1040" alt="Haven's welcome screen in a phone browser" loading="lazy">
|
||||
<figcaption>Joining from a phone browser. No app needed.</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div class="prose">
|
||||
<h3 style="margin-top: 36px;">What the server connects to</h3>
|
||||
<p class="muted small" style="margin-top: 6px;">Every outside service a Haven server contacts, and when.</p>
|
||||
</div>
|
||||
@@ -532,35 +551,55 @@
|
||||
<section id="screenshots">
|
||||
<div class="wrap">
|
||||
<div class="section-head">
|
||||
<h2>More screenshots</h2>
|
||||
<h2>Gallery</h2>
|
||||
</div>
|
||||
<div class="gallery">
|
||||
<figure><img class="zoomable" src="img/haven-screen-share.jpg" width="1200" height="591" alt="Screen sharing with voice chat and more than one stream"></figure>
|
||||
<figure><img class="zoomable" src="img/haven-theme-chat.jpg" width="1200" height="593" alt="The login screen with the theme picker"></figure>
|
||||
<figure><img class="zoomable" src="img/haven-theme-crt.jpg" width="1200" height="630" alt="A DM window and profile card in the CRT theme"></figure>
|
||||
<figure><img class="zoomable" src="img/haven-theme-braid.jpg" width="1200" height="631" alt="A chat channel in the Braid theme"></figure>
|
||||
<figure><img class="zoomable" src="img/haven-screen-share.jpg" width="1200" height="591" alt="Screen sharing with voice chat and more than one stream" loading="lazy"></figure>
|
||||
<figure><img class="zoomable" src="img/haven-theme-chat.jpg" width="1200" height="593" alt="The login screen with the theme picker" loading="lazy"></figure>
|
||||
<figure><img class="zoomable" src="img/haven-theme-crt.jpg" width="1916" height="1006" alt="A DM window and profile card in the CRT theme" loading="lazy"></figure>
|
||||
<figure><img class="zoomable" src="img/haven-theme-braid.jpg" width="1918" height="1009" alt="A chat channel in the Braid theme" loading="lazy"></figure>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<div class="lightbox" id="lightbox" role="dialog" aria-modal="true" aria-label="Enlarged screenshot" tabindex="-1" hidden><img alt=""></div>
|
||||
<div class="lightbox" id="lightbox" role="dialog" aria-modal="true" aria-label="Enlarged screenshot" tabindex="-1" hidden>
|
||||
<button class="lb-nav lb-prev" type="button" aria-label="Previous screenshot">‹</button>
|
||||
<img alt="">
|
||||
<button class="lb-nav lb-next" type="button" aria-label="Next screenshot">›</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Screenshots open full size; click anywhere or press Escape to close.
|
||||
// Screenshots open full size. The arrow keys, or the arrows on screen, step
|
||||
// through every screenshot on the page; click anywhere else or press Escape
|
||||
// to close.
|
||||
(() => {
|
||||
const box = document.getElementById('lightbox');
|
||||
if (!box) return;
|
||||
const big = box.querySelector('img');
|
||||
const open = (img) => { big.src = img.currentSrc || img.src; big.alt = img.alt; box.hidden = false; document.body.style.overflow = 'hidden'; box.focus(); };
|
||||
const shots = Array.from(document.querySelectorAll('img.zoomable'));
|
||||
let current = -1;
|
||||
const show = (i) => {
|
||||
current = (i + shots.length) % shots.length;
|
||||
const img = shots[current];
|
||||
big.src = img.currentSrc || img.src; big.alt = img.alt;
|
||||
};
|
||||
const open = (img) => { show(shots.indexOf(img)); box.hidden = false; document.body.style.overflow = 'hidden'; box.focus(); };
|
||||
const close = () => { box.hidden = true; big.removeAttribute('src'); document.body.style.overflow = ''; };
|
||||
document.querySelectorAll('img.zoomable').forEach((img) => {
|
||||
shots.forEach((img) => {
|
||||
img.tabIndex = 0; img.setAttribute('role', 'button'); img.setAttribute('aria-label', 'Enlarge screenshot');
|
||||
img.addEventListener('click', () => open(img));
|
||||
img.addEventListener('keydown', (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); open(img); } });
|
||||
});
|
||||
box.querySelector('.lb-prev').addEventListener('click', (e) => { e.stopPropagation(); show(current - 1); });
|
||||
box.querySelector('.lb-next').addEventListener('click', (e) => { e.stopPropagation(); show(current + 1); });
|
||||
box.addEventListener('click', close);
|
||||
document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && !box.hidden) close(); });
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (box.hidden) return;
|
||||
if (e.key === 'Escape') close();
|
||||
else if (e.key === 'ArrowRight' || e.key === 'ArrowDown') { e.preventDefault(); show(current + 1); }
|
||||
else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') { e.preventDefault(); show(current - 1); }
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 155 KiB |
|
After Width: | Height: | Size: 293 KiB |
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 330 KiB |
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 536 KiB |
@@ -7,11 +7,11 @@
|
||||
<meta property="og:description" content="Haven is a free, open source alternative to Discord that you host on your own computer. Channels, voice, screen sharing, threads and encrypted DMs. Friends join with a link, the desktop app or the Android app.">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="https://ancsemi.github.io/Haven/">
|
||||
<meta property="og:image" content="https://ancsemi.github.io/Haven/img/haven-4-5-default.jpg">
|
||||
<meta property="og:image" content="https://ancsemi.github.io/Haven/img/haven-4-6-default.jpg">
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:title" content="Haven, a chat server you run yourself">
|
||||
<meta name="twitter:description" content="Haven is a free, open source alternative to Discord that you host on your own computer. Channels, voice, screen sharing, threads and encrypted DMs. Friends join with a link, the desktop app or the Android app.">
|
||||
<meta name="twitter:image" content="https://ancsemi.github.io/Haven/img/haven-4-5-default.jpg">
|
||||
<meta name="twitter:image" content="https://ancsemi.github.io/Haven/img/haven-4-6-default.jpg">
|
||||
<meta name="twitter:site" content="@ancsemi">
|
||||
<link rel="canonical" href="https://ancsemi.github.io/Haven/">
|
||||
<meta name="theme-color" content="#F6F5F9">
|
||||
@@ -135,7 +135,10 @@
|
||||
/* ── Hero ────────────────────────────────────────── */
|
||||
.hero { padding-top: clamp(40px, 6vw, 72px); }
|
||||
.hero-grid { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); gap: clamp(28px, 5vw, 64px); align-items: start; }
|
||||
.hero .lead { font-size: 20px; line-height: 1.5; margin-top: 22px; max-width: 34em; }
|
||||
.hero-brand { display: inline-flex; align-items: center; gap: 0.32em; color: var(--ink); font-weight: 600; font-size: clamp(48px, 7vw, 76px); letter-spacing: 0.01em; line-height: 1; }
|
||||
.hero-brand svg { width: 1.05em; height: 1.05em; flex: none; }
|
||||
.hero-title { font-size: clamp(20px, 2.4vw, 25px); font-weight: 700; letter-spacing: -0.01em; margin-top: 30px; }
|
||||
.hero .lead { font-size: 20px; line-height: 1.5; margin-top: 10px; max-width: 34em; }
|
||||
.actions { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; margin-top: 30px; }
|
||||
.btn { display: inline-flex; align-items: center; gap: 8px; padding: 11px 18px; border-radius: 4px; font-weight: 600; font-size: 16px; text-decoration: none; border: 1px solid transparent; line-height: 1.2; }
|
||||
.btn-primary { background: var(--accent); color: var(--accent-ink); }
|
||||
@@ -166,8 +169,9 @@
|
||||
.cols > div:first-child { padding-left: 0; border-left: 0; }
|
||||
.cols > div:last-child { padding-right: 0; }
|
||||
.cols h3 { margin-bottom: 10px; padding-bottom: 8px; border-bottom: 1px solid var(--rule); }
|
||||
.cols ul { list-style: none; padding: 0; }
|
||||
.cols li { padding-left: 0; font-size: 16px; }
|
||||
.cols ul { list-style: disc; padding-left: 1.1em; }
|
||||
.cols li { font-size: 16px; }
|
||||
.cols li::marker { color: var(--accent); }
|
||||
.cols li + li { margin-top: 0.5em; }
|
||||
|
||||
/* ── Steps ───────────────────────────────────────── */
|
||||
@@ -205,6 +209,11 @@
|
||||
.lightbox { position: fixed; inset: 0; z-index: 50; background: rgba(10, 8, 16, 0.92); display: flex; align-items: center; justify-content: center; padding: 24px; cursor: zoom-out; }
|
||||
.lightbox[hidden] { display: none; }
|
||||
.lightbox img { max-width: 100%; max-height: 100%; border-radius: 6px; box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5); }
|
||||
.lb-nav { position: absolute; top: 50%; transform: translateY(-50%); width: 44px; height: 44px; border: 0; border-radius: 50%; background: rgba(255, 255, 255, 0.14); color: #fff; font-size: 30px; line-height: 1; cursor: pointer; display: grid; place-items: center; padding: 0 0 4px; }
|
||||
.lb-nav:hover { background: rgba(255, 255, 255, 0.26); }
|
||||
.lb-prev { left: 18px; }
|
||||
.lb-next { right: 18px; }
|
||||
@media (max-width: 700px) { .lb-nav { width: 36px; height: 36px; font-size: 24px; } .lb-prev { left: 8px; } .lb-next { right: 8px; } }
|
||||
|
||||
/* ── Facts ───────────────────────────────────────── */
|
||||
.facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 0; border-top: 1px solid var(--rule-strong); border-bottom: 1px solid var(--rule-strong); }
|
||||
@@ -263,6 +272,7 @@
|
||||
<a href="#compare">Compare</a>
|
||||
<a href="#setup">Setup</a>
|
||||
<a href="#security">Security</a>
|
||||
<a href="#screenshots">Gallery</a>
|
||||
<a href="#download">Download</a>
|
||||
<a href="https://github.com/ancsemi/Haven">GitHub</a>
|
||||
<a class="btn-try" id="try-now" href="#top">Try it now</a>
|
||||
@@ -275,7 +285,11 @@
|
||||
<div class="wrap">
|
||||
<div class="hero-grid">
|
||||
<div>
|
||||
<h1>A chat server you run yourself.</h1>
|
||||
<div class="hero-brand" aria-hidden="true">
|
||||
<svg viewBox="0 0 100 100"><polygon points="50,3 93,28 93,72 50,97 7,72 7,28" fill="none" stroke="currentColor" stroke-width="8" stroke-linejoin="round"/></svg>
|
||||
Haven
|
||||
</div>
|
||||
<h1 class="hero-title">A chat server you run yourself.</h1>
|
||||
<p class="lead">Haven is a free, open source alternative to Discord. It runs on your own computer, your friends join with a link, and there's no company in the middle.</p>
|
||||
<div class="actions">
|
||||
<a class="btn btn-primary" href="https://github.com/ancsemi/Haven/archive/refs/tags/v4.6.0.zip">Download Haven <span class="ver">4.6.0</span></a>
|
||||
@@ -300,15 +314,14 @@
|
||||
</div>
|
||||
</div>
|
||||
<figure class="shot">
|
||||
<img class="zoomable" src="img/haven-4-6-default.jpg" width="1600" height="843" alt="Haven's default theme: channels and DMs on the left, the member list on the right">
|
||||
<img class="zoomable" src="img/haven-4-6-default.jpg" width="1918" height="1010" alt="Haven's default theme: channels and DMs on the left, the member list on the right">
|
||||
</figure>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="about">
|
||||
<div class="wrap">
|
||||
<div class="split">
|
||||
<div class="prose">
|
||||
<div class="prose">
|
||||
<div class="section-head">
|
||||
<h2>About</h2>
|
||||
</div>
|
||||
@@ -316,11 +329,6 @@
|
||||
<p>There's no company in the middle. No account with us, no email or phone number, and nothing to pay for. Your messages, files and voice calls stay on your own server.</p>
|
||||
<p>Haven has been in development since February 2026. It's a spare-time project and it'll always be free.</p>
|
||||
<p>Many helpful people with a shared passion for free, unfiltered and private chat have come together to improve it. Every change is public, with a <a href="https://github.com/ancsemi/Haven/blob/main/CHANGELOG.md">changelog</a> updated every release.</p>
|
||||
</div>
|
||||
<figure class="fig">
|
||||
<img class="zoomable" src="img/haven-phone-welcome.jpg" width="480" height="1040" alt="Haven's welcome screen in a phone browser">
|
||||
<figcaption>Joining from a phone browser. No app needed.</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -354,10 +362,9 @@
|
||||
<div>
|
||||
<h3>Customization</h3>
|
||||
<ul>
|
||||
<li>26 themes, or write your own CSS</li>
|
||||
<li>26 themes with customizable effects, or write your own CSS</li>
|
||||
<li>Bots and webhooks</li>
|
||||
<li>Sign in with your own identity provider</li>
|
||||
<li>Backups and updates from the settings page</li>
|
||||
<li>Guest access, invite links and channel codes</li>
|
||||
<li>Available in 8 languages</li>
|
||||
</ul>
|
||||
@@ -368,9 +375,13 @@
|
||||
<li>Rich Presence: show what you're playing or listening to</li>
|
||||
<li>Built-in games with leaderboards</li>
|
||||
<li>Flash games, through Ruffle</li>
|
||||
<li>Backups and updates from the settings page</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<figure class="shot">
|
||||
<img class="zoomable" src="img/haven-features.jpg" width="1915" height="1005" alt="A community channel in the Braid theme with the member list open" loading="lazy">
|
||||
</figure>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -427,7 +438,8 @@
|
||||
<h2>Security and privacy</h2>
|
||||
<p>How it actually works.</p>
|
||||
</div>
|
||||
<div class="prose">
|
||||
<div class="split">
|
||||
<div class="prose">
|
||||
<ul>
|
||||
<li><strong>Your data lives on the computer running the server,</strong> in one folder. Back it up, move it or delete it whenever you want.</li>
|
||||
<li><strong>Direct messages are end-to-end encrypted.</strong> The server stores them but can't read them, and neither can the admin.</li>
|
||||
@@ -436,6 +448,13 @@
|
||||
<li><strong>No telemetry.</strong> The server doesn't send usage data or crash reports anywhere.</li>
|
||||
<li><strong>There's no central Haven server and no Haven account.</strong> Nothing to leak.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<figure class="fig">
|
||||
<img class="zoomable" src="img/haven-phone-welcome.jpg" width="480" height="1040" alt="Haven's welcome screen in a phone browser" loading="lazy">
|
||||
<figcaption>Joining from a phone browser. No app needed.</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
<div class="prose">
|
||||
<h3 style="margin-top: 36px;">What the server connects to</h3>
|
||||
<p class="muted small" style="margin-top: 6px;">Every outside service a Haven server contacts, and when.</p>
|
||||
</div>
|
||||
@@ -532,35 +551,55 @@
|
||||
<section id="screenshots">
|
||||
<div class="wrap">
|
||||
<div class="section-head">
|
||||
<h2>More screenshots</h2>
|
||||
<h2>Gallery</h2>
|
||||
</div>
|
||||
<div class="gallery">
|
||||
<figure><img class="zoomable" src="img/haven-screen-share.jpg" width="1200" height="591" alt="Screen sharing with voice chat and more than one stream"></figure>
|
||||
<figure><img class="zoomable" src="img/haven-theme-chat.jpg" width="1200" height="593" alt="The login screen with the theme picker"></figure>
|
||||
<figure><img class="zoomable" src="img/haven-theme-crt.jpg" width="1200" height="630" alt="A DM window and profile card in the CRT theme"></figure>
|
||||
<figure><img class="zoomable" src="img/haven-theme-braid.jpg" width="1200" height="631" alt="A chat channel in the Braid theme"></figure>
|
||||
<figure><img class="zoomable" src="img/haven-screen-share.jpg" width="1200" height="591" alt="Screen sharing with voice chat and more than one stream" loading="lazy"></figure>
|
||||
<figure><img class="zoomable" src="img/haven-theme-chat.jpg" width="1200" height="593" alt="The login screen with the theme picker" loading="lazy"></figure>
|
||||
<figure><img class="zoomable" src="img/haven-theme-crt.jpg" width="1916" height="1006" alt="A DM window and profile card in the CRT theme" loading="lazy"></figure>
|
||||
<figure><img class="zoomable" src="img/haven-theme-braid.jpg" width="1918" height="1009" alt="A chat channel in the Braid theme" loading="lazy"></figure>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<div class="lightbox" id="lightbox" role="dialog" aria-modal="true" aria-label="Enlarged screenshot" tabindex="-1" hidden><img alt=""></div>
|
||||
<div class="lightbox" id="lightbox" role="dialog" aria-modal="true" aria-label="Enlarged screenshot" tabindex="-1" hidden>
|
||||
<button class="lb-nav lb-prev" type="button" aria-label="Previous screenshot">‹</button>
|
||||
<img alt="">
|
||||
<button class="lb-nav lb-next" type="button" aria-label="Next screenshot">›</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Screenshots open full size; click anywhere or press Escape to close.
|
||||
// Screenshots open full size. The arrow keys, or the arrows on screen, step
|
||||
// through every screenshot on the page; click anywhere else or press Escape
|
||||
// to close.
|
||||
(() => {
|
||||
const box = document.getElementById('lightbox');
|
||||
if (!box) return;
|
||||
const big = box.querySelector('img');
|
||||
const open = (img) => { big.src = img.currentSrc || img.src; big.alt = img.alt; box.hidden = false; document.body.style.overflow = 'hidden'; box.focus(); };
|
||||
const shots = Array.from(document.querySelectorAll('img.zoomable'));
|
||||
let current = -1;
|
||||
const show = (i) => {
|
||||
current = (i + shots.length) % shots.length;
|
||||
const img = shots[current];
|
||||
big.src = img.currentSrc || img.src; big.alt = img.alt;
|
||||
};
|
||||
const open = (img) => { show(shots.indexOf(img)); box.hidden = false; document.body.style.overflow = 'hidden'; box.focus(); };
|
||||
const close = () => { box.hidden = true; big.removeAttribute('src'); document.body.style.overflow = ''; };
|
||||
document.querySelectorAll('img.zoomable').forEach((img) => {
|
||||
shots.forEach((img) => {
|
||||
img.tabIndex = 0; img.setAttribute('role', 'button'); img.setAttribute('aria-label', 'Enlarge screenshot');
|
||||
img.addEventListener('click', () => open(img));
|
||||
img.addEventListener('keydown', (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); open(img); } });
|
||||
});
|
||||
box.querySelector('.lb-prev').addEventListener('click', (e) => { e.stopPropagation(); show(current - 1); });
|
||||
box.querySelector('.lb-next').addEventListener('click', (e) => { e.stopPropagation(); show(current + 1); });
|
||||
box.addEventListener('click', close);
|
||||
document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && !box.hidden) close(); });
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (box.hidden) return;
|
||||
if (e.key === 'Escape') close();
|
||||
else if (e.key === 'ArrowRight' || e.key === 'ArrowDown') { e.preventDefault(); show(current + 1); }
|
||||
else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') { e.preventDefault(); show(current - 1); }
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
|
||||