web: state the no-server/in-browser privacy clearly + self-host fonts
- Make the privacy promise true: bundle the fonts (Poppins/Inter/JetBrains Mono latin subsets + the text-security mask font) under helwasm/assets/fonts/ and drop the Google Fonts + jsDelivr links. The page now makes zero external requests once loaded — it talks to no third party. - Say it plainly throughout the UI: a "Private by design" callout in the About panel, the meta description, the quick-gen and console hints, and the footer — nothing you type leaves the browser, no server, no account, no tracking.
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+18
-12
@@ -5,17 +5,13 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
||||||
<meta name="theme-color" content="#0a2540" />
|
<meta name="theme-color" content="#0a2540" />
|
||||||
<title>LesS/KEY — password generator</title>
|
<title>LesS/KEY — password generator</title>
|
||||||
|
<meta name="description" content="A password manager that stores nothing and never talks to a server. Passwords are generated entirely in your browser with WebAssembly; your master password and your data never leave your device." />
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="./assets/favicon-32x32.png" />
|
<link rel="icon" type="image/png" sizes="32x32" href="./assets/favicon-32x32.png" />
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="./assets/favicon-16x16.png" />
|
<link rel="icon" type="image/png" sizes="16x16" href="./assets/favicon-16x16.png" />
|
||||||
<link rel="icon" href="./assets/favicon.ico" sizes="any" />
|
<link rel="icon" href="./assets/favicon.ico" sizes="any" />
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="./assets/apple-touch-icon.png" />
|
<link rel="apple-touch-icon" sizes="180x180" href="./assets/apple-touch-icon.png" />
|
||||||
<link rel="manifest" href="./assets/site.webmanifest" />
|
<link rel="manifest" href="./assets/site.webmanifest" />
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
<!-- Fonts are self-hosted in style.css (./assets/fonts/) — no external requests. -->
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
||||||
<link
|
|
||||||
href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap"
|
|
||||||
rel="stylesheet"
|
|
||||||
/>
|
|
||||||
<link rel="stylesheet" href="./style.css" />
|
<link rel="stylesheet" href="./style.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -49,6 +45,13 @@
|
|||||||
master always produce the same password — so there is nothing secret to leak,
|
master always produce the same password — so there is nothing secret to leak,
|
||||||
sync, or back up, and you only ever remember one phrase.
|
sync, or back up, and you only ever remember one phrase.
|
||||||
</p>
|
</p>
|
||||||
|
<p class="about-privacy">
|
||||||
|
<strong>Private by design.</strong> Everything happens on your device. Your master
|
||||||
|
password and the passwords it generates are never sent anywhere, never stored on a
|
||||||
|
server, and never logged — there is no account, no sync, and no tracking. The app is a
|
||||||
|
single page plus a WebAssembly module, with its fonts bundled in; once it has loaded,
|
||||||
|
it makes no network requests at all.
|
||||||
|
</p>
|
||||||
<div class="about-grid">
|
<div class="about-grid">
|
||||||
<div>
|
<div>
|
||||||
<h4>Quick password</h4>
|
<h4>Quick password</h4>
|
||||||
@@ -62,8 +65,9 @@
|
|||||||
<h4>Console</h4>
|
<h4>Console</h4>
|
||||||
<p>
|
<p>
|
||||||
The full command line — type <code>help</code> for every command. Your list of
|
The full command line — type <code>help</code> for every command. Your list of
|
||||||
names lives only in this browser (localStorage); use <strong>Export</strong> /
|
names lives only in this browser (localStorage), never on a server; use
|
||||||
<strong>Import</strong> to move it (e.g. to and from a Notion page).
|
<strong>Export</strong> / <strong>Import</strong> to move it yourself (e.g. to and
|
||||||
|
from a Notion page).
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -77,7 +81,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<p class="about-note">
|
<p class="about-note">
|
||||||
Runs the real hel engine compiled to WebAssembly — the exact same generator as the
|
Runs the real hel engine compiled to WebAssembly — the exact same generator as the
|
||||||
command-line tool. Nothing is ever sent to a server.
|
command-line tool. No server, no account, no tracking — nothing to leak.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</details>
|
</details>
|
||||||
@@ -88,8 +92,9 @@
|
|||||||
<h2>Quick password</h2>
|
<h2>Quick password</h2>
|
||||||
<p class="hint">
|
<p class="hint">
|
||||||
Deterministic — the same name + master always regenerate the same
|
Deterministic — the same name + master always regenerate the same
|
||||||
password. The result updates live as you type. Nothing is stored unless
|
password. The result updates live as you type, entirely in your browser —
|
||||||
you press <strong>Store</strong>.
|
your master and the generated password never leave this device. Nothing is
|
||||||
|
stored unless you press <strong>Store</strong>.
|
||||||
</p>
|
</p>
|
||||||
<div class="fields">
|
<div class="fields">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
@@ -132,6 +137,7 @@
|
|||||||
|
|
||||||
<footer class="foot wrap">
|
<footer class="foot wrap">
|
||||||
Runs the real hel core compiled to WebAssembly — same generator as the CLI.
|
Runs the real hel core compiled to WebAssembly — same generator as the CLI.
|
||||||
|
Everything runs in your browser; nothing you type is ever sent to a server.
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<div class="toast" id="toast"></div>
|
<div class="toast" id="toast"></div>
|
||||||
@@ -470,7 +476,7 @@
|
|||||||
bg.addEventListener("click", (e) => e.target === bg && bg.classList.remove("show"))
|
bg.addEventListener("click", (e) => e.target === bg && bg.classList.remove("show"))
|
||||||
);
|
);
|
||||||
|
|
||||||
appendLine('<span class="muted"># LesS/KEY ready — runs the real hel core via WASM. Try: help</span>');
|
appendLine('<span class="muted"># LesS/KEY ready — runs entirely in your browser (WASM); nothing is sent to a server. Try: help</span>');
|
||||||
}
|
}
|
||||||
boot();
|
boot();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
+17
-6
@@ -20,14 +20,18 @@
|
|||||||
--radius: 16px;
|
--radius: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Self-hosted fonts — bundled with the app so it makes NO external requests and
|
||||||
|
talks to no third party (no Google Fonts, no CDN). Latin subset only. */
|
||||||
|
@font-face { font-family:"Poppins"; font-style:normal; font-weight:600; font-display:swap; src:url("./assets/fonts/Poppins-600.woff2") format("woff2"); }
|
||||||
|
@font-face { font-family:"Poppins"; font-style:normal; font-weight:700; font-display:swap; src:url("./assets/fonts/Poppins-700.woff2") format("woff2"); }
|
||||||
|
@font-face { font-family:"Inter"; font-style:normal; font-weight:400; font-display:swap; src:url("./assets/fonts/Inter-400.woff2") format("woff2"); }
|
||||||
|
@font-face { font-family:"Inter"; font-style:normal; font-weight:500; font-display:swap; src:url("./assets/fonts/Inter-500.woff2") format("woff2"); }
|
||||||
|
@font-face { font-family:"Inter"; font-style:normal; font-weight:600; font-display:swap; src:url("./assets/fonts/Inter-600.woff2") format("woff2"); }
|
||||||
|
@font-face { font-family:"JetBrains Mono"; font-style:normal; font-weight:400; font-display:swap; src:url("./assets/fonts/JetBrainsMono-400.woff2") format("woff2"); }
|
||||||
|
@font-face { font-family:"JetBrains Mono"; font-style:normal; font-weight:500; font-display:swap; src:url("./assets/fonts/JetBrainsMono-500.woff2") format("woff2"); }
|
||||||
/* Masked-secret font: dots glyphs so the real chars stay selectable/copyable.
|
/* Masked-secret font: dots glyphs so the real chars stay selectable/copyable.
|
||||||
WebKit/Blink use -webkit-text-security; Firefox falls back to this font. */
|
WebKit/Blink use -webkit-text-security; Firefox falls back to this font. */
|
||||||
@font-face {
|
@font-face { font-family:"text-security-disc"; font-display:swap; src:url("./assets/fonts/text-security-disc.woff2") format("woff2"); }
|
||||||
font-family: "text-security-disc";
|
|
||||||
src: url("https://cdn.jsdelivr.net/npm/text-security/dist/text-security-disc.woff2") format("woff2"),
|
|
||||||
url("https://cdn.jsdelivr.net/npm/text-security/dist/text-security-disc.woff") format("woff");
|
|
||||||
font-display: swap;
|
|
||||||
}
|
|
||||||
|
|
||||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||||
html { height: 100%; }
|
html { height: 100%; }
|
||||||
@@ -115,6 +119,13 @@ main { padding: clamp(20px, 3vw, 34px) 0 56px; display: grid; gap: clamp(16px, 2
|
|||||||
.about-grid h4 { font-family: var(--disp); font-weight: 600; font-size: 14px; color: var(--ink); margin-bottom: 5px; }
|
.about-grid h4 { font-family: var(--disp); font-weight: 600; font-size: 14px; color: var(--ink); margin-bottom: 5px; }
|
||||||
.about-grid p { font-size: 13.5px; }
|
.about-grid p { font-size: 13.5px; }
|
||||||
.about-note { font-family: var(--mono); font-size: 12px; margin-top: 10px; }
|
.about-note { font-family: var(--mono); font-size: 12px; margin-top: 10px; }
|
||||||
|
/* Privacy callout — make the "no server" promise visually prominent. */
|
||||||
|
.about-privacy {
|
||||||
|
margin: 6px 0 2px; padding: 13px 16px; border-radius: 12px;
|
||||||
|
border: 1px solid var(--line); border-left: 3px solid var(--ocean);
|
||||||
|
background: rgba(27, 65, 97, 0.045); color: var(--ink); font-size: 14.5px; max-width: 76ch;
|
||||||
|
}
|
||||||
|
.about-privacy strong { color: var(--ocean); }
|
||||||
@media (max-width: 680px) { .about-grid { grid-template-columns: 1fr; } }
|
@media (max-width: 680px) { .about-grid { grid-template-columns: 1fr; } }
|
||||||
|
|
||||||
/* Cards */
|
/* Cards */
|
||||||
|
|||||||
Reference in New Issue
Block a user