LiveInboxPreview.tsxfeat(onboarding): a setup flow that shows you the product while you configure it
Adds `/onboarding-setup` — a sidebar-driven flow over the four surfaces a new
user actually has to configure (Inbox, sub-inboxes, Tasks, Pipeline), each step
paired with a live preview of the real product rather than a screenshot of it.
Reachable from the profile menu as "Set up Cedar".
Two inbox-creation races surfaced by clicking through the template gallery are
fixed on the way, since the flow leans on that path hard:
- Per-mutation `invalidateQueries` lost rows. Create #1's refetch was issued
after #2 had written its optimistic row, so a server list predating #2 landed
last and overwrote it — the row vanished and the template card flipped back to
unselected. Now the last create to settle does the single refetch.
- Two adds fired back to back both read the cache before either had written to
it and claimed the same position, so a run of template clicks piled up at one
index and the tab strip reordered itself on refetch. Positions are now issued
from a carried-forward high-water mark.
A failed create drops only its own row instead of restoring a whole snapshot,
and `removeInbox` no longer swallows the rejection — callers holding their own
selected-state need to hear about it, or the row returns while the card stays
deselected.
Co-Authored-By: Claude Opus 5 (1M context) <<email>>Aug 31, 2026, 10:48 PMmock-threads.tsfeat(onboarding): a setup flow that shows you the product while you configure it
Adds `/onboarding-setup` — a sidebar-driven flow over the four surfaces a new
user actually has to configure (Inbox, sub-inboxes, Tasks, Pipeline), each step
paired with a live preview of the real product rather than a screenshot of it.
Reachable from the profile menu as "Set up Cedar".
Two inbox-creation races surfaced by clicking through the template gallery are
fixed on the way, since the flow leans on that path hard:
- Per-mutation `invalidateQueries` lost rows. Create #1's refetch was issued
after #2 had written its optimistic row, so a server list predating #2 landed
last and overwrote it — the row vanished and the template card flipped back to
unselected. Now the last create to settle does the single refetch.
- Two adds fired back to back both read the cache before either had written to
it and claimed the same position, so a run of template clicks piled up at one
index and the tab strip reordered itself on refetch. Positions are now issued
from a carried-forward high-water mark.
A failed create drops only its own row instead of restoring a whole snapshot,
and `removeInbox` no longer swallows the rejection — callers holding their own
selected-state need to hear about it, or the row returns while the card stays
deselected.
Co-Authored-By: Claude Opus 5 (1M context) <<email>>Aug 31, 2026, 10:48 PMPreviewInbox.tsxfeat(onboarding): a setup flow that shows you the product while you configure it
Adds `/onboarding-setup` — a sidebar-driven flow over the four surfaces a new
user actually has to configure (Inbox, sub-inboxes, Tasks, Pipeline), each step
paired with a live preview of the real product rather than a screenshot of it.
Reachable from the profile menu as "Set up Cedar".
Two inbox-creation races surfaced by clicking through the template gallery are
fixed on the way, since the flow leans on that path hard:
- Per-mutation `invalidateQueries` lost rows. Create #1's refetch was issued
after #2 had written its optimistic row, so a server list predating #2 landed
last and overwrote it — the row vanished and the template card flipped back to
unselected. Now the last create to settle does the single refetch.
- Two adds fired back to back both read the cache before either had written to
it and claimed the same position, so a run of template clicks piled up at one
index and the tab strip reordered itself on refetch. Positions are now issued
from a carried-forward high-water mark.
A failed create drops only its own row instead of restoring a whole snapshot,
and `removeInbox` no longer swallows the rejection — callers holding their own
selected-state need to hear about it, or the row returns while the card stays
deselected.
Co-Authored-By: Claude Opus 5 (1M context) <<email>>Aug 31, 2026, 10:48 PM