Lemmy – Quick Sign In Mockup
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Lemmy – Join the Fediverse</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<!-- LANDING -->
<section id="landing" class="page active">
<img class="logo" src="https://join-lemmy.org/logo.svg" alt="Lemmy logo" />
<h1 class="brand">Lemmy</h1>
<p class="tagline">
A <span class="accent">community-owned</span> social network<br />
for the <span class="accent">fediverse</span>.
</p>
<div class="cta">
<button class="btn btn-primary" id="quickSignIn">
Quick Sign In
</button>
<button class="btn btn-secondary" id = "setupWizard">
Use Setup Wizard
</button>
</div>
</section>
<!-- SIGNUP -->
<section id="signup" class="page">
<h1 class="brand small">Join the Fediverse</h1>
<form class="signup-form">
<label>
Choose a Username
<input type="text" placeholder="yourname" required />
</label>
<label>
Enter your Email Address <span class="optional">(optional)</span>
<input type="email" placeholder="[email protected]" />
</label>
<label>
Choose a Password
<input type="password" id="password" required />
<div class="strength-meter">
<div id="strengthBar"></div>
</div>
<div id="strengthText" class="strength-text">Strength: —</div>
</label>
<label>
Choose a Server
<select id="serverSelect"></select>
</label>
<p class="helper">
A server was randomly chosen for you. Don’t worry, it doesn’t matter
which one you choose first and you can always change servers later.
</p>
<button type="submit" class="btn btn-primary giant full">
Join the Fediverse
</button>
</form>
</section>
<script src="script.js"></script>
</body>
</html>
CSS
:root {
--bg: #0b0f0d;
--bg-soft: #121816;
--text: #e9fff1;
--muted: #9fd9b6;
--primary: #63ff9b;
--primary-strong: #38e27d;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
background: radial-gradient(circle at top, #0f1a14, #050706);
color: var(--text);
font-family: system-ui, -apple-system, BlinkMacSystemFont,
"Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif;
overflow-x: hidden;
}
/* Pages */
.page {
max-width: 760px;
margin: 0 auto;
padding: 4.5rem 1.5rem 4rem;
text-align: center;
display: none;
}
.page.active {
display: block;
}
/* Logo */
.logo {
width: 140px;
margin-bottom: 2rem;
filter: drop-shadow(0 0 20px rgba(99,255,155,.25));
}
/* Brand */
.brand {
font-size: 3.4rem;
font-weight: 800;
letter-spacing: 0.04em;
color: var(--primary);
text-shadow:
0 0 12px rgba(99,255,155,.8),
0 0 50px rgba(99,255,155,.4);
animation: glowPulse 3s ease-in-out infinite;
}
.brand.small {
font-size: 2.6rem;
}
/* Tagline */
.tagline {
margin-top: 1.5rem;
font-size: 1.4rem;
line-height: 1.45;
}
.accent {
color: var(--primary);
font-weight: 700;
text-shadow: 0 0 12px rgba(99,255,155,.6);
}
/* CTA */
.cta {
margin-top: 3.2rem;
display: flex;
flex-direction: column;
gap: 1.25rem;
align-items: center;
}
/* Buttons */
.btn {
position: relative;
min-width: 320px;
padding: 1.1rem 2rem;
border-radius: 10px;
border: none;
cursor: pointer;
font-size: 1.15rem;
overflow: hidden;
transition: transform .15s ease;
}
.btn-primary {
background: linear-gradient(135deg, var(--primary), var(--primary-strong));
color: #052312;
font-weight: 700;
font-size: 1.3rem;
box-shadow:
0 0 30px rgba(99,255,155,.6),
0 0 60px rgba(99,255,155,.4);
}
.btn-secondary {
background: var(--bg-soft);
color: var(--text);
border: 1px solid...
JavaScript
const servers = [
"lemmy.today",
"discuss.online",
"lemmy.world",
"random.lemmy"
];
const landing = document.getElementById("landing");
const signup = document.getElementById("signup");
const quickSignIn = document.getElementById("quickSignIn");
const setupWizardBtn = document.getElementById("setupWizard");
const serverSelect = document.getElementById("serverSelect");
const passwordInput = document.getElementById("password");
const strengthBar = document.getElementById("strengthBar");
const strengthText = document.getElementById("strengthText");
/* Page switching */
quickSignIn.addEventListener("click", () => {
landing.classList.remove("active");
signup.classList.add("active");
});
/* Setup Wizard alert */
setupWizardBtn.addEventListener("click", () => {
alert("This will open up the usual 'Join a Server' wizard.");
});
/* Populate & randomize server */
servers.forEach(server => {
const option = document.createElement("option");
option.value = server;
option.textContent = server;
serverSelect.appendChild(option);
});
serverSelect.value =
servers[Math.floor(Math.random() * servers.length)];
/* Password strength meter */
passwordInput.addEventListener("input", e => {
const password = e.target.value;
let strength = 0;
if (password.length > 7) strength++;
if (/[A-Z]/.test(password)) strength++;
if (/[0-9]/.test(password)) strength++;
if (/[^A-Za-z0-9]/.test(password)) strength++;
const levels = [
{ w: "25%", c: "red", t: "Weak" },
{ w: "50%", c: "orange", t: "Fair" },
{ w: "75%", c: "yellow", t: "Good" },
{ w: "100%", c: "lime", t: "Strong" }
];
if (strength === 0) {
strengthBar.style.width = "0%";
strengthText.textContent = "Strength: —";
} else {
const l = levels[strength - 1];
strengthBar.style.width = l.w;
strengthBar.style.background = l.c;
strengthText.textContent = `Strength: ${l.t}`;
}
});