Skip to content

Commit cf2fd79

Browse files
committed
feat(landing): replace waitlist CTA with get-started section
Swap the final-CTA waitlist signup for a get-started flow: a quickstart docker/psql code snippet, primary GitHub/Discord/docs links, and a Product Hunt link, with email capture repositioned as an optional release-updates signup. Also validates the email client-side before submitting, since the no-cors fetch always resolves regardless of input.
1 parent 0471fa8 commit cf2fd79

6 files changed

Lines changed: 89 additions & 23 deletions

File tree

assets/custom.css

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,22 @@ body:has(.oxidoc-landing) .oxidoc-skip-nav { display: none !important; }
791791
justify-content: center;
792792
}
793793

794+
/* Get-started actions + release-updates form (reworked <WaitlistForm>) */
795+
.oxidoc-landing waitlistform { max-width: 40rem; min-height: 0; }
796+
.oxidoc-landing .ndb-final .cw { max-width: 38rem; margin: 0 auto 1.5rem; text-align: left; }
797+
.oxidoc-landing .ndb-final .cw-body { text-align: left; }
798+
.ndb-wl-btn-primary {
799+
background: var(--ndb-indigo-600);
800+
border-color: transparent;
801+
color: #fff;
802+
font-weight: 600;
803+
}
804+
.ndb-wl-btn-primary:hover { background: var(--ndb-indigo-500); }
805+
.ndb-wl-updates { margin-top: 2.25rem; }
806+
.ndb-wl-updates-title { font-size: 1.05rem; font-weight: 600; color: #fff; margin: 0 0 0.2rem; }
807+
.ndb-wl-updates-sub { font-size: 0.85rem; color: var(--ndb-text-3); margin: 0 0 1.1rem; }
808+
.ndb-wl-ph-row { display: flex; justify-content: center; margin-top: 1.6rem; }
809+
794810
/* ── Banner / Product Hunt strip ───────────────────────────────────── */
795811

796812
body:has(.oxidoc-landing) .oxidoc-banner {

assets/js/code-window.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@
2222
' <span class="cw-kw">FINAL_TOP_K</span> <span class="cw-nm">10</span>\n' +
2323
' <span class="cw-kw">RRF_K</span> (<span class="cw-nm">60.0</span>, <span class="cw-nm">35.0</span>)\n' +
2424
' <span class="cw-kw">MAX_VISITED</span> <span class="cw-nm">1000</span>;',
25+
"quickstart":
26+
'<span class="cw-cm"># Start NodeDB — PostgreSQL wire protocol on 6432</span>\n' +
27+
'<span class="cw-kw">docker run</span> -d --name nodedb \\\n' +
28+
' -p <span class="cw-nm">6432</span>:<span class="cw-nm">6432</span> -p <span class="cw-nm">6433</span>:<span class="cw-nm">6433</span> -p <span class="cw-nm">6480</span>:<span class="cw-nm">6480</span> \\\n' +
29+
' -v nodedb-data:/var/lib/nodedb \\\n' +
30+
' <span class="cw-st">farhansyah/nodedb:latest</span>\n' +
31+
"\n" +
32+
'<span class="cw-cm"># Connect with any Postgres client</span>\n' +
33+
'<span class="cw-kw">psql</span> -h localhost -p <span class="cw-nm">6432</span>',
2534
};
2635

2736
function build(host) {

assets/js/landing-hero.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
'<p class="ndb-hero-sub">' + sub + "</p>" +
4444
'<div class="ndb-hero-actions">' +
4545
'<a class="ndb-btn ndb-btn-primary" href="' + github + '" target="_blank" rel="noopener">' + GITHUB + "<span>Star on GitHub</span></a>" +
46-
'<a class="ndb-btn ndb-btn-soft" href="#waitlist"><span>Get Early Access</span></a>' +
46+
'<a class="ndb-btn ndb-btn-soft" href="#get-started"><span>Get Started</span></a>' +
4747
'<a class="ndb-btn ndb-btn-outline" href="' + discord + '" target="_blank" rel="noopener">' + DISCORD + "<span>Join Discord</span></a>" +
4848
"</div>" +
4949
"</div>";

assets/js/landing-nav.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
'<a class="ndb-nav-link" href="/use-cases">Use Cases</a>' +
2626
'<a class="ndb-nav-icon" href="' + github + '" target="_blank" rel="noopener" aria-label="GitHub">' + GITHUB + '</a>' +
2727
'<a class="ndb-nav-icon" href="' + discord + '" target="_blank" rel="noopener" aria-label="Discord">' + DISCORD + '</a>' +
28-
'<a class="ndb-nav-cta" href="#waitlist">Join Waitlist</a>' +
28+
'<a class="ndb-nav-cta" href="#get-started">Get Started</a>' +
2929
"</div>" +
3030
"</nav>";
3131
}

assets/js/waitlist-form.js

Lines changed: 55 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
// Landing-page waitlist form + secondary actions, rendered by
2-
// <WaitlistForm action="…" github="…" discord="…" producthunt="…" />.
1+
// Landing-page get-started actions + release-updates form, rendered by
2+
// <WaitlistForm action="…" github="…" quickstart="…" discord="…" producthunt="…" />.
33
//
44
// RDX renders the component as a bare lowercased <waitlistform> element (no
55
// hyphen → not a valid custom-element name), so we upgrade it by query
66
// selector rather than via customElements.define. The MailerLite JSONP
77
// endpoint sends no CORS headers, so we POST with mode:"no-cors" and treat a
8-
// resolved fetch as success (the submission still reaches them).
8+
// resolved fetch as success (the submission still reaches them). Because that
9+
// fetch always resolves, the email is validated before we ever submit —
10+
// otherwise an empty or malformed address would land on the success state.
911

1012
(function () {
1113
var GITHUB =
@@ -14,6 +16,14 @@
1416
var DISCORD =
1517
'<svg viewBox="0 0 640 512" width="19" height="19" fill="currentColor" aria-hidden="true">' +
1618
'<path d="M524.5 69.8a1.5 1.5 0 0 0 -.8-.7A485.1 485.1 0 0 0 404.1 32a1.8 1.8 0 0 0 -1.9 .9 337.5 337.5 0 0 0 -14.9 30.6 447.8 447.8 0 0 0 -134.4 0 309.5 309.5 0 0 0 -15.1-30.6 1.9 1.9 0 0 0 -1.9-.9A483.7 483.7 0 0 0 116.1 69.1a1.7 1.7 0 0 0 -.8 .7C39.1 183.7 18.2 294.7 28.4 404.4a2 2 0 0 0 .8 1.4A487.7 487.7 0 0 0 176 479.9a1.9 1.9 0 0 0 2.1-.7A348.2 348.2 0 0 0 208.1 430.4a1.9 1.9 0 0 0 -1-2.6 321.2 321.2 0 0 1 -45.9-21.9 1.9 1.9 0 0 1 -.2-3.1c3.1-2.3 6.2-4.7 9.1-7.1a1.8 1.8 0 0 1 1.9-.3c96.2 43.9 200.4 43.9 295.5 0a1.8 1.8 0 0 1 1.9 .2c2.9 2.4 6 4.9 9.1 7.2a1.9 1.9 0 0 1 -.2 3.1 301.4 301.4 0 0 1 -45.9 21.8 1.9 1.9 0 0 0 -1 2.6 391.1 391.1 0 0 0 30 48.8 1.9 1.9 0 0 0 2.1 .7A486 486 0 0 0 610.7 405.7a1.9 1.9 0 0 0 .8-1.4C623.7 277.6 590.9 167.5 524.5 69.8zM222.5 337.6c-29 0-52.8-26.6-52.8-59.2S193.1 219.1 222.5 219.1c29.7 0 53.3 26.8 52.8 59.2C275.3 311 251.9 337.6 222.5 337.6zm195.4 0c-29 0-52.8-26.6-52.8-59.2S388.4 219.1 417.9 219.1c29.7 0 53.3 26.8 52.8 59.2C470.7 311 447.3 337.6 417.9 337.6z"/></svg>';
19+
var BOOK =
20+
'<svg viewBox="0 0 448 512" width="16" height="16" fill="currentColor" aria-hidden="true">' +
21+
'<path d="M96 0C43 0 0 43 0 96V416c0 53 43 96 96 96H384h32c17.7 0 32-14.3 32-32s-14.3-32-32-32V384c17.7 0 32-14.3 32-32V32c0-17.7-14.3-32-32-32H384 96zM64 416c0-17.7 14.3-32 32-32H352v64H96c-17.7 0-32-14.3-32-32zM128 136c0-4.4 3.6-8 8-8H328c4.4 0 8 3.6 8 8v16c0 4.4-3.6 8-8 8H136c-4.4 0-8-3.6-8-8V136zm8 56H328c4.4 0 8 3.6 8 8v16c0 4.4-3.6 8-8 8H136c-4.4 0-8-3.6-8-8V200c0-4.4 3.6-8 8-8z"/></svg>';
22+
23+
// Pragmatic email check: non-empty local part, single @, dotted domain.
24+
// Stricter than type="email"'s native rule, which accepts things like "a@b".
25+
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
26+
var ERR_DEFAULT = "Something went wrong — try again, or ping us on Discord.";
1727

1828
function attr(host, name, fallback) {
1929
var v = host.getAttribute(name);
@@ -23,36 +33,64 @@
2333
function build(host) {
2434
var action = attr(host, "action", "");
2535
var github = attr(host, "github", "https://github.com/NodeDB-Lab/nodedb");
36+
var quickstart = attr(host, "quickstart", "/docs/introduction/quickstart");
2637
var discord = attr(host, "discord", "https://discord.gg/s54gDMVc7B");
2738
var ph = attr(host, "producthunt", "https://www.producthunt.com/products/nodedb");
2839

2940
host.innerHTML =
30-
'<form class="ndb-wl-form" action="' + action + '" method="post" novalidate>' +
31-
'<input class="ndb-wl-email" type="email" name="fields[email]" required ' +
32-
'autocomplete="email" placeholder="you@work.com" aria-label="Work email" />' +
33-
'<input type="hidden" name="ml-submit" value="1" />' +
34-
'<input type="hidden" name="anticsrf" value="true" />' +
35-
'<button class="ndb-wl-submit" type="submit"><span class="ndb-wl-label">Get Early Access</span></button>' +
36-
"</form>" +
37-
'<p class="ndb-wl-msg ndb-wl-error" role="alert" hidden>Something went wrong — try again, or ping us on Discord.</p>' +
38-
'<div class="ndb-wl-msg ndb-wl-success" hidden>' +
39-
"<strong>You're on the list.</strong> Check your inbox for a confirmation email. See you on launch day — May 1." +
40-
"</div>" +
4141
'<div class="ndb-wl-actions">' +
42-
'<a class="ndb-wl-btn" href="' + github + '" target="_blank" rel="noopener">' + GITHUB + "<span>Star on GitHub</span></a>" +
42+
'<a class="ndb-wl-btn ndb-wl-btn-primary" href="' + github + '" target="_blank" rel="noopener">' + GITHUB + "<span>Star on GitHub</span></a>" +
43+
'<a class="ndb-wl-btn" href="' + quickstart + '">' + BOOK + "<span>Read the Quickstart</span></a>" +
4344
'<a class="ndb-wl-btn" href="' + discord + '" target="_blank" rel="noopener">' + DISCORD + "<span>Join Discord</span></a>" +
44-
'<a class="ndb-wl-btn ndb-wl-btn-ph" href="' + ph + '" target="_blank" rel="noopener"><span class="ndb-wl-ph-mark">P</span><span>Product Hunt</span></a>' +
45+
"</div>" +
46+
'<div class="ndb-wl-updates">' +
47+
'<p class="ndb-wl-updates-title">Want release updates?</p>' +
48+
'<p class="ndb-wl-updates-sub">New engines, benchmarks, and the 1.0 launch — no spam, unsubscribe anytime.</p>' +
49+
'<form class="ndb-wl-form" action="' + action + '" method="post">' +
50+
'<input class="ndb-wl-email" type="email" name="fields[email]" required ' +
51+
'autocomplete="email" placeholder="you@work.com" aria-label="Work email" />' +
52+
'<input type="hidden" name="ml-submit" value="1" />' +
53+
'<input type="hidden" name="anticsrf" value="true" />' +
54+
'<button class="ndb-wl-submit" type="submit"><span class="ndb-wl-label">Notify me</span></button>' +
55+
"</form>" +
56+
'<p class="ndb-wl-msg ndb-wl-error" role="alert" hidden>' + ERR_DEFAULT + "</p>" +
57+
'<div class="ndb-wl-msg ndb-wl-success" hidden>' +
58+
"<strong>You're subscribed.</strong> Check your inbox to confirm — we'll email you on new releases and the 1.0 launch." +
59+
"</div>" +
60+
"</div>" +
61+
'<div class="ndb-wl-ph-row">' +
62+
'<a class="ndb-wl-btn ndb-wl-btn-ph" href="' + ph + '" target="_blank" rel="noopener"><span class="ndb-wl-ph-mark">P</span><span>See us on Product Hunt</span></a>' +
4563
"</div>";
4664

4765
var form = host.querySelector("form");
66+
var email = host.querySelector(".ndb-wl-email");
4867
var btn = host.querySelector(".ndb-wl-submit");
4968
var label = host.querySelector(".ndb-wl-label");
5069
var errEl = host.querySelector(".ndb-wl-error");
5170
var okEl = host.querySelector(".ndb-wl-success");
5271

72+
function showError(msg) {
73+
errEl.textContent = msg || ERR_DEFAULT;
74+
errEl.hidden = false;
75+
btn.disabled = false;
76+
label.textContent = "Notify me";
77+
}
78+
5379
form.addEventListener("submit", function (e) {
5480
e.preventDefault();
5581
errEl.hidden = true;
82+
83+
// Validate before submitting. The no-cors fetch below always resolves,
84+
// so without this guard an empty or malformed email would still show the
85+
// success state. reportValidity() surfaces the native browser bubble.
86+
var value = email.value.trim();
87+
email.value = value;
88+
if (!EMAIL_RE.test(value) || !form.checkValidity()) {
89+
form.reportValidity();
90+
showError("Please enter a valid email address.");
91+
return;
92+
}
93+
5694
btn.disabled = true;
5795
label.textContent = "Submitting…";
5896

@@ -70,9 +108,7 @@
70108
okEl.hidden = false;
71109
})
72110
.catch(function () {
73-
errEl.hidden = false;
74-
btn.disabled = false;
75-
label.textContent = "Get Early Access";
111+
showError();
76112
});
77113
});
78114
}

home.rdx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,17 @@ WHERE ST_DWithin(location, ST_Point(-73.99, 40.75), 2000)
139139
<Faq />
140140
</Section>
141141

142-
<Section id="waitlist" class="ndb-final">
143-
<CTA title="Ship AI products, not plumbing." description="Get early access to the launch. We'll send you the repo, the benchmarks, and the design-partner invite." />
142+
<Section id="get-started" class="ndb-final">
143+
<CTA title="Ship AI products, not plumbing." description="NodeDB is in public preview and already running in real projects. Pull the image, point any Postgres client at it, and start building." />
144+
145+
<CodeWindow snippet="quickstart" title="run it in 30 seconds" lang="bash" />
146+
147+
Pre-1.0 and moving fast — follow the [road to 1.0](https://github.com/orgs/NodeDB-Lab/projects/7).
144148

145149
<WaitlistForm
146150
action="https://assets.mailerlite.com/jsonp/2289342/forms/185571144953234582/subscribe"
147151
github="https://github.com/NodeDB-Lab/nodedb"
152+
quickstart="/docs/introduction/quickstart"
148153
discord="https://discord.gg/s54gDMVc7B"
149154
producthunt="https://www.producthunt.com/products/nodedb"
150155
/>

0 commit comments

Comments
 (0)