feat: add newsletter signup section to landing page
Adds a Listmonk-powered newsletter form at the bottom of the rSpace landing page, matching the dark theme and gradient styling of existing sections. Uses rSpace list UUID for subscriber routing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
91d600ed93
commit
095d6e1eb9
|
|
@ -285,7 +285,66 @@
|
|||
border-color: rgba(124, 58, 237, 0.6);
|
||||
}
|
||||
|
||||
/* Newsletter */
|
||||
.newsletter-form {
|
||||
max-width: 440px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.newsletter-row {
|
||||
display: flex;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.newsletter-input {
|
||||
flex: 1;
|
||||
padding: 12px 16px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.15);
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
color: white;
|
||||
font-size: 1rem;
|
||||
outline: none;
|
||||
transition: border-color 0.2s;
|
||||
}
|
||||
|
||||
.newsletter-input:focus {
|
||||
border-color: #14b8a6;
|
||||
}
|
||||
|
||||
.newsletter-input::placeholder {
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.newsletter-btn {
|
||||
padding: 12px 24px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.newsletter-status {
|
||||
font-size: 0.875rem;
|
||||
margin-top: 0.75rem;
|
||||
min-height: 1.25em;
|
||||
}
|
||||
|
||||
.newsletter-status.success {
|
||||
color: #22c55e;
|
||||
}
|
||||
|
||||
.newsletter-status.error {
|
||||
color: #ef4444;
|
||||
}
|
||||
|
||||
.newsletter-privacy {
|
||||
font-size: 0.8rem;
|
||||
color: #64748b;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.newsletter-row {
|
||||
flex-direction: column;
|
||||
}
|
||||
.pillars {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
|
@ -517,6 +576,29 @@
|
|||
</a>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-divider"></div>
|
||||
<h2>Stay Connected</h2>
|
||||
<p class="section-subtitle">
|
||||
Get updates on rSpace development, new ecosystem modules, and community features.
|
||||
</p>
|
||||
|
||||
<form class="newsletter-form" id="newsletter-form">
|
||||
<div class="newsletter-row">
|
||||
<input
|
||||
type="email"
|
||||
id="newsletter-email"
|
||||
placeholder="your@email.com"
|
||||
required
|
||||
class="newsletter-input"
|
||||
/>
|
||||
<button type="submit" class="newsletter-btn" id="newsletter-btn">Subscribe</button>
|
||||
</div>
|
||||
<p class="newsletter-status" id="newsletter-status"></p>
|
||||
<p class="newsletter-privacy">No spam, unsubscribe anytime.</p>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
import { RStackIdentity } from "@shared/components/rstack-identity";
|
||||
import { RStackAppSwitcher } from "@shared/components/rstack-app-switcher";
|
||||
|
|
@ -529,6 +611,48 @@
|
|||
fetch("/api/modules").then(r => r.json()).then(data => {
|
||||
document.querySelector("rstack-app-switcher")?.setModules(data.modules || []);
|
||||
}).catch(() => {});
|
||||
|
||||
// Newsletter signup
|
||||
const newsletterForm = document.getElementById("newsletter-form");
|
||||
const newsletterEmail = document.getElementById("newsletter-email");
|
||||
const newsletterBtn = document.getElementById("newsletter-btn");
|
||||
const newsletterStatus = document.getElementById("newsletter-status");
|
||||
|
||||
newsletterForm.addEventListener("submit", async (e) => {
|
||||
e.preventDefault();
|
||||
const email = newsletterEmail.value.trim();
|
||||
if (!email) return;
|
||||
|
||||
newsletterBtn.disabled = true;
|
||||
newsletterBtn.textContent = "Subscribing...";
|
||||
newsletterStatus.textContent = "";
|
||||
newsletterStatus.className = "newsletter-status";
|
||||
|
||||
try {
|
||||
const res = await fetch("https://newsletter.jeffemmett.com/subscribe", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
email,
|
||||
list_uuid: "2d247234-34cf-4ee6-858f-2b5e24e2e5dc",
|
||||
}),
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
newsletterStatus.textContent = "Welcome to the network. The space expands.";
|
||||
newsletterStatus.className = "newsletter-status success";
|
||||
newsletterEmail.value = "";
|
||||
} else {
|
||||
throw new Error("Subscription failed");
|
||||
}
|
||||
} catch {
|
||||
newsletterStatus.textContent = "Something went wrong. Please try again.";
|
||||
newsletterStatus.className = "newsletter-status error";
|
||||
} finally {
|
||||
newsletterBtn.disabled = false;
|
||||
newsletterBtn.textContent = "Subscribe";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Reference in New Issue