A full email client inside the workspace with AI triage, smart replies, autocomplete, thread grouping, and attachment handling.
Inbox Layout
The inbox is a two-panel view: a 180px folder sidebar on the left and the message list on the right.
Folders
| Folder | Badge |
|---|---|
| Inbox | unread count |
| Follow-ups | follow-up count |
| Starred | — |
| Sent | — |
| Drafts | — |
| Archive | — |
| Trash | — |
Click Compose at the top of the sidebar to open a new email.
Thread Grouping
Emails are grouped by threadId, falling back to normalized subject (strips Re:, Fwd:, Fw: prefixes). Each thread row shows:
- Unread indicator dot (union of
unread,!seen, or!is_readacross all messages) - Sender name + thread count chip (when > 1 message)
- Subject line
- Snippet preview
- Relative timestamp via dayjs
fromNow()
Search
Type a query and press Enter to search via goSvc.searchEmails(query). Switching folders clears the search.
Reading Email
Click a thread to open EmailView. On open, the email is automatically marked as read.
Thread View
When a thread has multiple messages, each is rendered as a collapsible card sorted oldest-to-newest. The most recent message is expanded by default. Collapsed cards show sender, date, and an attachment indicator.
Quoted text (detected by On ... wrote:, > prefixes, --- Original Message, From:/Sent: patterns) is hidden behind a "..." toggle.
All HTML bodies are sanitized with DOMPurify before rendering.
Action Bar
| Action | Behavior |
|---|---|
| Star | optimistic toggle via goSvc.starEmail() |
| Archive | moves to archive, navigates back |
| Delete | moves to trash, navigates back |
| Triage | inline Select — urgent, needs_reply, fyi, spam |
| Snooze | popover with 4 presets: 1 hour, 4 hours, tomorrow 9am, next Monday 9am |
AI Features
| Feature | API Call | Output |
|---|---|---|
| Summarize | goSvc.summarizeEmail(id) | summary banner above the thread |
| Suggest Replies | goSvc.suggestReplies(id) | clickable chips; clicking one opens compose with that text pre-filled |
| Priority Triage | automatic | numeric priority chip — red ≥ 80, amber ≥ 50, green otherwise |
Contact Sidebar
A 200px right panel shows sender details when contact data exists: name, email, company, title, email count, last contact date.
Open Tracking
If tracking data exists, a green chip shows "Opened Nx · X ago".
Composing Email
The compose view has fields for To (comma-separated), Subject, and Body (multiline textarea).
AI Autocomplete (Ghost Text)
After you stop typing for 800ms (body must be > 10 characters), goSvc.autocomplete(body, replyToId) is called. The suggestion appears as italic ghost text below the textarea. Press Tab to accept and append it to your message.
AI Draft
In reply mode only, click AI Draft to call goSvc.draftReply(replyToId). The AI-generated response replaces the body text for your review.
Attachments
Upload files via the attach button or drag-and-drop onto the textarea. Each file is uploaded immediately to the server via goSvc.uploadAttachment(file) and shown as a deletable chip. Attachments are sent as { blobId, name, type, size } objects.
Snippets
Click the snippets icon to open a menu of saved text snippets (fetched from goSvc.listSnippets() on mount). Selecting one appends its content to the body.
Schedule Send
A popover offers 3 preset send times: Tomorrow 9am, Tomorrow 1pm, Monday 9am.
Downloading Attachments
In EmailView, each attachment renders as a download chip. Clicking it fetches the blob via goSvc.getAttachmentUrl(emailId, blobId) with a Bearer token, creates an object URL, triggers a download, and revokes the URL.