Overview
The inboxes table is defined in the schema but there is no UI or backend logic to connect, manage, or monitor email sending accounts. Inboxes are a core primitive — campaigns can't send without them. This issue covers both the Convex backend and the full /inboxes UI.
Current State
convex/inboxes/schema.ts — table defined, no queries or mutations
- No
/inboxes route exists
- Campaign creation form has no inbox selector
- No inbox health/status tracking
Tasks
1. Convex Backend (Queries & Mutations)
2. /inboxes Page — Inbox List View
3. Connect Inbox Flow (Modal/Drawer)
4. Inbox Detail & Edit
5. Wire Inbox into Campaign Creation
Acceptance Criteria
Design Notes
- Follow the same two-panel / framer-motion step pattern used in
NewCampaignForm
- Use
Sheet (not Dialog) for the edit flow — it's less disruptive for a settings-like surface
- Status badges and progress bars should use the existing shadcn
Badge and Progress components
- Keep provider logos as simple SVG icons, not third-party image CDN URLs
References
convex/inboxes/schema.ts — existing table definition
convex/campaigns/schema.ts — campaigns reference inboxId
src/components/pages/(auth)/campaigns/new/NewCampaignForm.tsx — step pattern to follow
src/app/(auth)/campaigns/layout.tsx — layout pattern for new auth route
Overview
The
inboxestable is defined in the schema but there is no UI or backend logic to connect, manage, or monitor email sending accounts. Inboxes are a core primitive — campaigns can't send without them. This issue covers both the Convex backend and the full/inboxesUI.Current State
convex/inboxes/schema.ts— table defined, no queries or mutations/inboxesroute existsTasks
1. Convex Backend (Queries & Mutations)
convex/inboxes/queries.tslist— returns all inboxes for the current user, ordered bycreatedAtget— returns a single inbox by ID (with ownership check)getStats— returns sent count, bounce rate, last-sent timestamp per inboxconvex/inboxes/mutations.tscreate— creates a new inbox record (SMTP/IMAP credentials stored encrypted, or OAuth token reference)update— update display name, daily send limit, reply-to addressremove— soft-delete with adeletedAttimestamp, disallow if active campaigns reference itsetStatus— toggleactive | paused | errorstatusconvex/inboxes/actions.tstestConnection— sends a test email via the stored credentials to verify connectivity; updateslastTestedAtandconnectionStatus2.
/inboxesPage — Inbox List Viewsrc/app/(auth)/inboxes/page.tsxInboxCardcomponent — shows:active(green) /paused(yellow) /error(red)/inboxeslink to the sidebar nav3. Connect Inbox Flow (Modal/Drawer)
ConnectInboxDialog— multi-step drawer:testConnectionaction and show result before savingNewCampaignFormpattern)4. Inbox Detail & Edit
EditInboxSheet— side sheet (not full page) for editing an existing inbox5. Wire Inbox into Campaign Creation
NewCampaignForm— shows connected inboxes with status badgesinboxIdon the campaign record when creatingAcceptance Criteria
/inboxeswith live status and send statsDesign Notes
NewCampaignFormSheet(notDialog) for the edit flow — it's less disruptive for a settings-like surfaceBadgeandProgresscomponentsReferences
convex/inboxes/schema.ts— existing table definitionconvex/campaigns/schema.ts— campaigns referenceinboxIdsrc/components/pages/(auth)/campaigns/new/NewCampaignForm.tsx— step pattern to followsrc/app/(auth)/campaigns/layout.tsx— layout pattern for new auth route