Put real money on your daily walk. Finish the week and get your stake back. Walka gives you the accountability that motivation can't.
Sports & fitnessHTML · JavaScriptGitHub @getwalkaOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗Static marketing site (no framework, no build step) deployed on Vercel. Each
page is a self-contained .html file with its own inline <style>; routing
is just file-based plus the /invite/:path* rewrite in vercel.json.
PostHog is wired into every page for analytics.
/moms)A standalone, flagged-off onboarding + checkout experiment living alongside
the main site, built to test whether postpartum/pregnant mums will sign up
and commit under a gentler commitment mechanic. It does not touch the main
flow or its stake logic (it does link to the shared /terms and /privacy
pages).
Cohort only. Solo is out of scope for this flow, it's hidden behind a
separate feature flag on mobile, not built here. Every /moms signup joins
a cohort group.
As of 2026-10-31, /moms is a two-screen flow: home (a full marketing-
style landing page, no quiz) then checkout. This replaces the earlier
13-screen onboarding quiz (motherhood stage, motivations, barriers,
interludes, connection, conversations, baseline, clearance, contact,
preparing, results) entirely, the same landing+checkout shape the
November-challenge funnel (couch6k.html/couch6k-copy.js/
couch6k-app.js) already moved to. Matching/personalization questions
("which stage are you") are gone from this page; that happens in the app
after signup instead, same as couch6k moved coach selection post-purchase.
STEP_IDS in moms-app.js is now just ["home", "checkout"]; COPY.landing,
COPY.cohort, and RESULTS_COPY (the old quiz's personalization data) were
deleted along with the quiz, and moms_landing_view no longer fires (see
moms_home_viewed below instead).
Files:
moms.html: the route itself (page shell, styles, landing + checkout
markup containers). Styled to match myplan.html (same Anton/Inter
fonts, same lavender/cream/pink/mint palette, same button/spacing system)
rather than this funnel's older sage/Quicksand look, which moms-success.html
still uses.moms-copy.js: every piece of copy and every tunable config value
(feature flag key, Stripe link/mode, plan price/billing interval). Edit
this file, not the others, to change wording or pricing.moms-app.js: the step engine (state machine, resume, analytics,
Supabase sync, Stripe handoff). Shouldn't contain user-facing strings.moms-success.html: where Stripe redirects after a successful payment.supabase/moms_leads.sql: schema + RLS policy for the leads table (run
once in the Supabase SQL editor). The quiz-answer columns (motherhood
stage, motivations, barriers, etc.) stay in the schema, nullable and
simply no longer written to.Gated by a PostHog feature flag (PostHog is already on every page):
moms-postpartum-flow (see FEATURE_FLAG_KEY in moms-copy.js) and
release it to whoever should see the test./moms?preview=1 once in a browser. That unlocks the flow on that
device via localStorage, regardless of the flag. /moms?preview=0
removes the override./moms is additionally restricted to US and Canadian visitors
(GEO_ALLOWED_COUNTRIES in moms-copy.js), independent of the feature flag
above.
middleware.js (Vercel Edge Middleware, matches /moms only) reads
Vercel's own x-vercel-ip-country request header and stamps it onto a
walka_geo_country cookie. This is the one piece of this experiment that
isn't purely static: everything else here is plain files with no build
step, this is a small edge function. No npm dependency, no @vercel/edge
package; it hand-writes the x-middleware-next: 1 response header that
tells Vercel to keep serving the static route rather than replacing the
response.moms-app.js reads that cookie and, if the country isn't in the allowed
list, shows COPY.geoGate instead of the wizard. The decision lives
here, not in middleware, so there's one place (same as the feature-flag
gate) that owns who gets in.vercel dev or a
local file open), the visitor is let through rather than blocked. A
detection hiccup should never cost a real US/CA signup.?preview=1 bypasses this gate too, same as the feature flag, so QA can
test from any location.moms_leads.country (upserted on landing, before onboarding even starts)
and sent as a moms_geo_blocked PostHog event when someone is actually
blocked, so the country breakdown is visible in both places, not just the
pass/fail outcome.This is a single one-time payment for a fixed-length challenge, not a subscription. There's no payment backend in this repo, so checkout hands off to one Stripe-hosted Payment Link; we never touch card data ourselves.
TOTAL_CHARGE_CENTS in moms-copy.js (stake +
entry fee, currently $49.99). Do not use a recurring/subscription price,
and do not create separate links for the stake and the fee, it's one
checkout.https://getwalka.com/moms-success.https://buy.stripe.com/test_... URL into
COHORT_PAYMENT_LINK.test in moms-copy.js.COHORT_PAYMENT_LINK.live, and flip STRIPE_MODE from "test" to
"live". That's the entire switch (also hides the test-mode card note
on checkout, it's gated on STRIPE_MODE).Card test number: 4242 4242 4242 4242, any future expiry, any CVC.
All in moms-copy.js, cohort only, no tiers or choices shown:
PROGRAM_LENGTH_WEEKS: 4 weeks.COHORT_STAKE_AMOUNT_CENTS: $39.99 total stake, a cent under $40 on
purpose (same under-the-round-number pattern as the main app's $19.99
entry), returned in full if you don't miss every day.ENTRY_FEE_CENTS: $10 total, platform revenue, not refundable. Marketed
as "~$2.50/week" but charged as this one upfront amount, never billed
weekly; a real weekly charge would make it a recurring subscription
collected outside IAP, which this flow must not do, same invariant as
the main app.MISS_AMOUNT_CENTS_PER_DAY: $2, applies from day one. No grace period,
no free "life happened" passes, every missed day costs $2 (missing all
20 weekdays forfeits effectively the full $39.99 stake, one cent over on
paper; the mechanic caps forfeiture at the stake itself). Money from
missed days goes into the pool split among cohort members who finish,
same mechanic as the main app's weekly cohorts. The checkout screen
shows this as "-$2 from your stake," not a bare "$2," so it doesn't
read as a separate charge due today.TOTAL_CHARGE_CENTS: stake + fee, what the single Payment Link actually
charges ($49.99).Prepare mode never charges anyone. If clearance_status !== "yes",
there's no step goal to miss (the plan preview/checkout copy and the
miss_cents field written to Supabase both reflect "not tracked"/"no goal
yet" rather than the $2 figure) and, as of 2026-10, no Stripe checkout at
all: the "Pay" button
is replaced with "Reserve my spot," which skips the Payment Link entirely,
upserts the lead with checkout_status: "reserved" and the email/name
they entered, and shows an on-page "you're on the list" confirmation.
Follow-up (emailing them once they're cleared, to come back and actually
pay) is manual for now, there's no automated re-engagement built here.
Earlier versions of this flow charged the full stake upfront in prepare
mode too ("reserving a spot" with a refundable stake); that's been
replaced because asking for a real card charge before someone can even
start wasn't the right call.
The cohort step is no longer a choice (it was, until 2026-10; see the
manual test checklist for the old pick-and-mismatch-warning behavior this
replaced). It auto-places from weeks_postpartum, read-only (0–13 weeks
-> 0–3mo, 13–26 -> 3–6mo, otherwise 6–12mo; pregnant always lands in "Due
soon"; postpartum with no weeks answer, that field is optional, falls
back to 0–3mo rather than leaving the group unresolved).
Onboarding answers are upserted to Supabase after every step (so drop-offs
are captured too, not just completions), using the local_id generated in
the browser as the upsert key.
supabase/moms_leads.sql once in your Supabase project's SQL editor.SUPABASE_URL and SUPABASE_ANON_KEY (Project Settings → API,
the anon/public key only, never the service role key) in
moms-copy.js.select its own row by local_id, that
policy exists only because Postgres requires it to resolve
upsert()'s ON CONFLICT under RLS, see the note in
supabase/moms_leads.sql. Without it, every single upsert, including
a brand-new row with nothing to conflict with, fails outright with a
row-level security error. This isn't a hypothetical: it's exactly
what silently broke lead capture for this flow until the select
policy was added, so don't remove it as a "we don't need reads"
cleanup.All fire via the existing PostHog instance, prefixed moms_ (see EVENTS in
moms-copy.js): moms_onboarding_start, moms_step_viewed,
moms_step_completed, moms_dropoff, moms_home_viewed,
moms_checkout_viewed, moms_checkout_started, moms_checkout_completed,
moms_checkout_failed, moms_geo_blocked. The quiz-specific events
(moms_clearance_answered, moms_motivation_chosen, moms_cohort_chosen,
moms_prepare_reserved) were retired along with the quiz; a flag set up in
PostHog around any of those is now dead.
COHORT_PAYMENT_LINK, now with no screen above it
explaining those numbers. This is a known gap, not an oversight: the
checkout rework depends on deciding how the subscription is actually
billed (see the architecture question below) before touching it.COHORT_PAYMENT_LINK can point at a recurring price
once the checkout screen itself is reworked for the subscription (not
yet done; see above). Stripe bills recurring charges automatically
regardless of what this repo tracks; what's missing without a webhook
is our own record of renewals/failures/cancellations.link-moms-subscriber (Edge Function, in the main stepr repo's
supabase/functions/, not here) is the first piece of that: called
from /moms-success right after the Stripe redirect, same "replaces a
webhook, call it on return" pattern the main app's
sync-subscription-status already uses. Payment Links don't hand back
a customer/subscription id in the redirect URL, so it looks the Stripe
Customer up by the email already on the moms_leads row and writes
stripe_customer_id + subscription_status (mirrors Stripe's own
subscription.status) back onto that row. Public, unauthenticated
(the moms funnel never creates a Supabase session), gated only on
knowing the row's local_id, same trust model as every other write
here.moms_leads row to an actual app
account. When someone downloads the app and signs up with the same
email, nothing yet copies stripe_customer_id onto their new
profiles row. That means extending handle_new_user(), the trigger
that creates a profiles row for every signup app-wide, so it's
deliberately held until there's a real recurring Payment Link and a
tested link-moms-subscriber run to reconcile against, given the blast
radius of a mistake there (every signup, not just moms subscribers).
Once that exists, the main app's own
(already built, called on cold start) picks up the real status from
Stripe with no further moms-specific code./moms with the PostHog flag off and no ?preview=1 shows the
"not open yet" gate, no flow visible./moms?preview=1 unlocks the flow on that device; ?preview=0
relocks it./moms goes straight
into the wizard as normal; a moms_leads row appears with country
set to US/CA even before completing the first step./moms shows the "not available
in your country yet" gate instead of the wizard; a moms_geo_blocked
event fires in PostHog and the moms_leads row's country reflects
that country with last_step: "geo_blocked"./moms?preview=1 from that same non-US/CA VPN still unlocks the full
flow (preview bypasses the geo gate, not just the feature flag)./start)Same pattern as /moms above (quiz -> paywall -> inline Stripe checkout ->
success page, no Supabase session, a local_id-scoped leads table), aimed at
anyone rather than pregnancy/postpartum specifically. Files: start.html,
start-copy.js, start-app.js, start-success.html,
supabase/start_leads.sql.
Goal, current average daily steps, a difficulty pick (easy/medium/hard), coach personality (princess/tough, same two personas the app already has), solo-or-group, and -- solo only -- a stake amount. The stake step is skipped entirely for a group pick: a shared weekly cohort has one fixed stake, not a per-user choice, so the paywall shows the cohort's real price instead of asking for one.
/momscreate-start-subscription-intent) and then,
immediately after and without asking for card details again, the
refundable stake (create-start-stake-intent, a one-time PaymentIntent
against the same saved payment method). No Payment Link fallback for this
funnel -- a Payment Link can't carry the second charge, so a Stripe.js load
failure shows an error instead of degrading to a redirect.get-weekly-cohort-preview
(public, no auth) returns the real next cohort's step goal, stake, entry
fee, start date and spots left, read fresh from challenges the same way
lib/weeklyCohort.ts's getNextJoinableCohort() does in the app. The stake
actually charged is resolved the same way, server-side, inside
create-start-stake-intent -- never trusted from the client.apply-pending-web-plan (an authenticated Edge
Function, not a widened handle_new_user() trigger) plus
hooks/usePendingWebPlan.ts in the main app, called once per signed-in
session. It looks up start_leads by the signed-in user's email, re-verifies
the stake PaymentIntent with Stripe, credits the wallet via the existing
apply_credit('top_up', ...) RPC, and writes coach_style, fitness_goal,
recommended_step_goal, weekly_mode, solo_stake and the subscriber
columns onto the profile -- the same fields in-app onboarding already
writes, so the existing home-screen cards (HomeFallbackCard,
StartSoloCard) pick the plan up with no new screen. Idempotent via
profiles.web_plan_applied_at.middleware.js/cookie gate /moms uses if this ever needs Canada./start?preview=1; start_leads
upserts after every step.stake step never appears; the paywall shows
get-weekly-cohort-preview's real numbers (step goal, stake, spots
left), not a user-editable amount.4242 4242 4242 4242 test card: both
PaymentIntents succeed against the same Customer (check the Stripe test
dashboard); start_leads has stripe_customer_id,
stripe_subscription_id and stake_payment_intent_id all populated;
redirect lands on /start-success.apply-pending-web-plan applies on first cold start (check
profiles.web_plan_applied_at, weekly_mode, coach_style,
recommended_step_goal); the wallet shows the stake credited
(credit_ledger, type = 'top_up', stripe_ref = the stake
PaymentIntent id); re-opening the app doesn't credit it twice./moms, /invite, /terms, /privacy are all unchanged.sync-subscription-status/moms-success or a
confirmation email is the plan, not yet wired in.moms_checkout_completed and
the Supabase checkout_status: "completed_unverified" fire when the
browser lands back on /moms-success with its own local_id in
localStorage. This is a strong signal, not cryptographic proof of
payment. Reconcile actual payments against the Stripe test/live dashboard.
If you want verified completion, that needs a backend (a serverless
function + Stripe secret key), flagged here rather than built, since you
explicitly chose the no-backend Payment Links approach.moms_dropoff (fired on tab-hide/close
before completion) is the closest signal we have to "gave up."
moms_checkout_failed currently only fires for a misconfigured Payment
Link (missing/placeholder URL), not a real card decline.localStorage, keyed by a client-generated local_id. Switching devices
mid-flow starts over.local_id. The
UUID is never shown in the UI or URL, so it isn't practically guessable,
but it's a real trade-off of skipping a backend; see
supabase/moms_leads.sql.<meta name="robots" content="noindex"> is set on
both moms.html and moms-success.html./terms and
/privacy. terms.html §15's governing law (Delaware) and arbitration
venue (San Francisco, CA, administered by AAA) are filled in. The
stake/fee/miss language on the /moms checkout screen is new copy and
hasn't had a legal look yet; get one before taking real payments.
privacy.html still has an unfilled EEA/UK data-transfer-mechanism
placeholder, only matters if this flow reaches EU/UK users.GOAL_OPTIONS in
moms-copy.js); there's no baseline/energy/delivery-type math behind it
anymore. The delivery-type question (vaginal/C-section/prefer not to
say) was dropped from the stage step entirely, since it no longer
affected anything the user could see. barriers is still collected
from the baseline step for segmentation in Supabase; it just no longer
drives a computed number or appears as goal-screen copy. The
delivery_type column stays in moms_leads for historical rows but
nothing writes to it going forward.moms_prepare_reserved fires
in PostHog; the Supabase row's checkout_status becomes reserved
and miss_cents stays null.client_reference_id and prefilled_email populated in
the URL./moms-success with a
personalized message; Supabase row's checkout_status becomes
completed_unverified.moms_dropoff fires in PostHog;
Supabase row retains last_step at wherever you stopped./moms:
resumes at the same step with a "welcome back" banner, answers intact./, /invite, /terms, /privacy are all unchanged.