From 40691c05c815f9c69f846f4a3218c7399a51a37b Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Sat, 2 May 2026 00:52:59 -0500 Subject: [PATCH] nav order matches page; pricing moved last; setup-intent attach fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Page section order is now: hero → pillars → how-it-works → inference → efficiency → comparison → enterprise → mission → local-first → safety → environmental → marketplace → viral → pricing → footer. Pricing is the last content block so visitors scroll the whole story before being asked to commit. Nav (desktop + mobile + dropdown) reordered to mirror the page: How it works → Enterprise → Mission ▾ → Marketplace → Pricing → About / Gallery / Account. Stripe attach bug: /api/link-customer was hitting POST /v1/payment_intents/{id} for every Intent regardless of type, so SetupIntents (seti_*) returned 404 from Stripe. Branched on the id prefix - SetupIntents go to /v1/setup_intents/{id} and skip the receipt_email param (PaymentIntent-only field). Caught from a live 422 in the dashboard the moment Will tested timing=later. --- src/main.el | 26 +++++++++++++++++++++----- src/nav.el | 11 +++++++---- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/main.el b/src/main.el index ff16ee4..b3fb60c 100644 --- a/src/main.el +++ b/src/main.el @@ -146,6 +146,10 @@ fn persist_founding_count(sold: Int) { // ── Page assembly ───────────────────────────────────────────────────────────── fn page(sold: Int, total: Int) -> String { + // Page order is the source of truth; nav must mirror it section-for-section. + // Pricing is intentionally last so a visitor can scroll the whole story + // (what / how / why / who-it's-for / safety / planet) before being asked + // to commit to a plan. return page_open() + nav() + hero() @@ -159,9 +163,9 @@ fn page(sold: Int, total: Int) -> String { + local_first() + safety() + environmental() - + pricing(sold, total) + marketplace() + viral() + + pricing(sold, total) + footer() + page_close() } @@ -521,11 +525,23 @@ fn handle_request(method: String, path: String, body: String) -> String { } } - // 3. Attach customer + receipt_email to the PaymentIntent + // 3. Attach customer to the live Intent. SetupIntents (seti_*) and + // PaymentIntents (pi_*) live at different REST endpoints, so + // branch on the id prefix. SetupIntents do not accept + // receipt_email - that's a PaymentIntent-only field. if !str_eq(lc_cus_id, "") { - let lc_attach_body: String = "customer=" + lc_cus_id + "&receipt_email=" + lc_email_enc - let lc_attach_url: String = "https://api.stripe.com/v1/payment_intents/" + lc_pi_id - let lc_attach: String = http_post_form_auth(lc_attach_url, lc_attach_body, lc_auth) + let lc_is_setup: Bool = str_starts_with(lc_pi_id, "seti_") + let lc_attach_url: String = if lc_is_setup { + "https://api.stripe.com/v1/setup_intents/" + lc_pi_id + } else { + "https://api.stripe.com/v1/payment_intents/" + lc_pi_id + } + let lc_attach_body: String = if lc_is_setup { + "customer=" + lc_cus_id + } else { + "customer=" + lc_cus_id + "&receipt_email=" + lc_email_enc + } + let _lc_attach: String = http_post_form_auth(lc_attach_url, lc_attach_body, lc_auth) } // 4. Upsert the Supabase waitlist row so /account can find this purchase by email diff --git a/src/nav.el b/src/nav.el index 3449818..7b34f27 100644 --- a/src/nav.el +++ b/src/nav.el @@ -9,8 +9,11 @@ fn nav() -> String {
\"Neuron\" +