// Onboarding — shown when no active trip exists. Single screen with three // optional sub-states (setup form, create-first-trip, plain "create trip"). const Onboarding = ({ mode, initial, onDone }) => { if (mode === 'setup') return ; return ; }; const SetupForm = ({ initial, onDone }) => { const [s, setS] = React.useState(initial || { github_owner: '', github_repo: '', content_prefix: 'content/travel', branch_prefix: 'travel/', timezone: '' }); const [busy, setBusy] = React.useState(false); const [err, setErr] = React.useState(''); const save = async () => { if (!s.github_owner.trim()) { setErr('github username required'); return; } setBusy(true); setErr(''); try { const out = await api.putSetup(s); onDone(out); } catch (e) { setErr(e.message); setBusy(false); } }; return (
01 · connect github

Where do posts land?

Only asked once. Stored per install.

{err &&
{err}
}
); }; const NewTripForm = ({ onDone }) => { const [slug, setSlug] = React.useState(''); const [title, setTitle] = React.useState(''); const [busy, setBusy] = React.useState(false); const [err, setErr] = React.useState(''); const [discovered, setDiscovered] = React.useState(null); // null = loading, [] = none React.useEffect(() => { let cancelled = false; api.discoverTrips() .then((list) => { if (!cancelled) setDiscovered((list || []).filter((t) => !t.known)); }) .catch(() => { if (!cancelled) setDiscovered([]); }); return () => { cancelled = true; }; }, []); const create = async () => { const s = slug.trim().toLowerCase(); if (!s) { setErr('slug required'); return; } setBusy(true); setErr(''); try { const trip = await api.createTrip({ slug: s, title: title.trim() }); onDone(trip); } catch (e) { setErr(e.message); setBusy(false); } }; const adopt = async (candSlug) => { setBusy(true); setErr(''); try { const trip = await api.adoptTrip(candSlug); onDone(trip); } catch (e) { setErr(e.message); setBusy(false); } }; const hasExisting = Array.isArray(discovered) && discovered.length > 0; return (
02 · open a trip

{hasExisting ? 'Pick an existing trip, or start a new one.' : 'Name your trip.'}

{hasExisting ? 'Branches already on your GitHub repo are listed below. Or type a new slug to start fresh.' : 'Creates the branch and a section page on GitHub now. Day posts still wait for you to hit publish.'}

{hasExisting && (
{discovered.map((c) => ( ))}
)}
{hasExisting ? 'or — new trip' : ''}
{err &&
{err}
}
); }; Object.assign(window, { Onboarding });