Sponsor shown on sign-in + new-member onboarding (username, optional profile)

- Sign-in page shows "You're joining the line of @X" when arriving via a sponsor
  link (/api/sponsor now returns the sponsor name + avatar).
- After a new account verifies (or signs up) with no username yet, an onboarding
  modal prompts for a username and an optional bio (both skippable), before the
  welcome tour.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-07 08:29:12 -05:00
parent 9fd85e0d6c
commit a4119d652d
3 changed files with 62 additions and 5 deletions
+30 -2
View File
@@ -11,6 +11,13 @@
}
if (c.rehearsal && $('faucetCard')) $('faucetCard').hidden = false;
} catch (e) {}
// if they arrived through a sponsor's link, show who they're joining under
(async () => {
try {
const sp = await (await fetch('/api/sponsor')).json();
if (sp && sp.invited && sp.name && $('sponsorNote')) { $('sponsorNoteName').textContent = sp.name; $('sponsorNote').hidden = false; }
} catch (e) {}
})();
async function api(path, body) {
const r = await (await fetch(path, { method: 'POST',
@@ -1255,16 +1262,37 @@
IAP.status('Fresh code sent.', 'ok');
}));
$('mcVerifyBtn').addEventListener('click', busy($('mcVerifyBtn'), async () => {
await api('/api/auth/email/verify', { email: $('mcEmail').value, code: $('mcCode').value });
const r = await api('/api/auth/email/verify', { email: $('mcEmail').value, code: $('mcCode').value });
IAP.status('You are in.', 'ok');
if (r.created && !(r.account && r.account.username)) await showOnboard(); // pick a username first
if (!(await showGauntlet())) await showLoginAd(); // welcome tour outranks the login ad
await render();
}));
})();
// new-member onboarding: choose a username, optionally a bio (both skippable)
function showOnboard() {
return new Promise(resolve => {
const m = $('onboardModal'); if (!m) return resolve();
m.hidden = false; $('obErr').hidden = true;
const done = () => { m.hidden = true; resolve(); };
$('obSkip').onclick = done;
$('obSave').onclick = async () => {
const u = $('obUsername').value.trim();
try {
if (u) await api('/api/my/profile', { username: u });
const bio = $('obBio').value.trim();
if (bio) await api('/api/my/profile-details', { bio });
done();
} catch (e) { $('obErr').hidden = false; $('obErr').textContent = e.message || 'Could not save that. Try a different username.'; }
};
});
}
$('signupBtn').addEventListener('click', busy($('signupBtn'), async () => {
await api('/api/signup', { email: $('suEmail').value, password: $('suPass').value });
const r = await api('/api/signup', { email: $('suEmail').value, password: $('suPass').value });
IAP.status('Welcome aboard. You are in.', 'ok');
if (!(r.account && r.account.username)) await showOnboard();
await render();
}));
$('loginBtn').addEventListener('click', busy($('loginBtn'), async () => {