FivFold - Logo

Email Kit

Full-featured email client with folders, threads, compose dialog, labels, and responsive layout. Includes both UI and backend scaffolding.

Quick reference

CLI commands

Bash
# Add UI components (inbox, compose, threads, etc.) npx @fivfold/ui add email # Add backend scaffolding (Express/NestJS + TypeORM) npx @fivfold/api add email --framework=nestjs --orm=typeorm # Use MongoDB + Mongoose npx @fivfold/api add email --framework=nestjs --orm=mongoose --database=mongodb # Use Express + Prisma npx @fivfold/api add email --framework=express --orm=prisma # Dry run to preview files npx @fivfold/ui add email --dry-run npx @fivfold/api add email --dry-run

Overview

The Email Kit provides a complete email client experience: folder sidebar, thread list, message view, compose dialog, labels, and recipient input with autocomplete. Each Kit in FivFold combines a polished frontend (built on shadcn/ui) with optional backend scaffolding for Express or NestJS. Supported combinations:

LayerOptions
FrameworkNestJS, Express
SQLTypeORM (PostgreSQL, MySQL, MariaDB, MSSQL), Prisma
NoSQLMongoose (MongoDB), Prisma (MongoDB connector)
Cloud NoSQLAzure Cosmos DB SDK, AWS DynamoDB SDK

Demo

This demo is presented with Mock Data

Folders

Guide

Step-by-step guides for the frontend UI and backend API integration. In the sidebar, choose Frontend first, then runtime through ORM, so proxy and CORS snippets match your app.

The Email Kit is built exclusively with shadcn/ui primitives. Follow the steps below to install, integrate, and customize the UI.

1Install the Email Kit

Run the FivFold UI CLI to add the Email Kit to your project. Ensure you have run npx @fivfold/ui init first.

Bash
npx @fivfold/ui add email

The Kit is copied to @/components/ui/kits/email/ (or your configured kits alias in fivfold.json).

2Generated file structure

The command creates a folder with multiple component files for easier development and customization:

File tree
kits/email/ types.ts # Shared types (FivFoldEmailFolder, FivFoldEmailThread, etc.) recipient-input.tsx # To/Cc/Bcc input with autocomplete (Command + Popover) thread-item.tsx # Thread list row with star button compose-dialog.tsx # Compose, reply, and forward dialog message-panel.tsx # Message detail with accordion and Reply/Reply All/Forward sidebar-content.tsx # Folders and labels sidebar index.tsx # Main EmailKit component and re-exports

3Import and use in your app

Import the main component and types from the kit folder:

app/email/page.tsx
import { EmailKit } from "@/components/ui/kits/email"; import type { FivFoldEmailThread, FivFoldEmailFolder } from "@/components/ui/kits/email"; export function EmailPage() { const [threads, setThreads] = useState<FivFoldEmailThread[]>([]); const [selectedFolderId, setSelectedFolderId] = useState("inbox"); return ( <EmailKit folders={folders} selectedFolderId={selectedFolderId} onFolderSelect={setSelectedFolderId} threads={threads} selectedThreadId={selectedThreadId} onThreadSelect={setSelectedThreadId} onCompose={() => setComposeOpen(true)} onSend={handleSend} onStar={handleStar} availableLabels={labels} /> ); }

4Props reference

The Email Kit exposes a single EmailKit component. Props are grouped by the UI section they control.

Folder Sidebar

Navigation for Inbox, Sent, Drafts, Trash, and custom folders. Uses Button, ScrollArea, Badge, Separator. Implemented in sidebar-content.tsx.

PropTypePurpose
foldersFivFoldEmailFolder[]List of folders (Inbox, Sent, Drafts, Trash, custom). Drives sidebar navigation.
selectedFolderIdstringCurrently selected folder. Controls which threads are shown.
onFolderSelect(id: string) => voidCallback when user selects a folder. Fetch threads for the new folder.
availableLabelsFivFoldEmailLabel[]Labels shown in sidebar for filtering. Optional.

Thread List

Scrollable list of email threads with sender, subject, snippet, datetime, labels, star toggle. Uses ScrollArea, Input, Badge. Each row is thread-item.tsx.

PropTypePurpose
threadsFivFoldEmailThread[]Threads for the current folder. Map from your API response.
selectedThreadIdstring | nullCurrently selected thread. Controls which message is shown.
onThreadSelect(id: string) => voidCallback when user selects a thread. Fetch message details.
searchValuestringSearch input value. Filter threads client-side or pass to API.
onSearchChange(value: string) => voidCallback when search input changes. Debounce and refetch.
onStar(threadId, starred) => voidCallback when user stars/unstars. Call PATCH /api/email/threads/:id.
loadingThreadsbooleanShows loading state in thread list while fetching.

Message Panel

Accordion-style message view with sender avatar, body, attachments, Reply/Reply All/Forward actions. Uses Accordion, Button, ScrollArea.

PropTypePurpose
messageFivFoldEmailMessage | nullThe selected message to display. From GET /api/email/threads/:id.
loadingMessagebooleanShows loading state while fetching message details.
onReply(message) => voidOpens compose with Reply pre-filled. Call onSend when submitted.
onReplyAll(message) => voidOpens compose with Reply All (To/Cc) pre-filled.
onForward(message) => voidOpens compose with Forward pre-filled.

Compose Dialog

To/Cc/Bcc recipient input with autocomplete (Command + Popover), subject, body. Uses Dialog, Input, Textarea, Badge.

PropTypePurpose
onCompose() => voidOpens the compose dialog. Typically set state to show dialog.
onSend(data) => voidCallback with to, cc, bcc, subject, body. Call POST /api/email/send.
composeTitlestringDialog title (e.g. "New Message", "Reply", "Forward").

5Integration with backend

You own the wiring

The step-by-step guides, environment variables, and dev-server proxy or rewrite examples are suggestions—not a mandated layout. You should read the generated files, your existing routes and auth, and your deployment topology, then choose URLs, origins, and headers that match your app. We encourage verifying every connection yourself before shipping.

Step-by-step: Email UI → API

Examples match the Frontend choice in the stack sidebar (Next.js). Your mount paths may differ; adjust prefixes to match how you register routes and proxies.

Next.js → API

Prefer rewrites in next.config.ts so browser code can use same-origin paths like /api/email/... while the dev server forwards to your backend. Alternatively set NEXT_PUBLIC_API_URL and call that base from client code.

next.config.ts
// next.config.ts — example rewrite to API on another port import type { NextConfig } from 'next'; const nextConfig: NextConfig = { async rewrites() { return [ { source: '/api/:path*', destination: 'http://localhost:3001/:path*', // your Nest/Express port }, ]; }, }; export default nextConfig;

If the app and API both use port 3000, run the API on a different port (e.g. 3001) or use a monorepo BFF pattern.

API → browser (CORS)

Allow your UI's dev origin on the API. For Next.js that is typically http://localhost:3000 (plus 127.0.0.1 if you use it).

Production

Use your real API base (e.g. https://api.example.com/email) and lock CORS to known web origins — not *.

Connecting Email (UI layer) data to your user system

The kit components are presentational: they do not know your user id. Your fetch layer must attach the authenticated user (header, cookie, or token) so the API returns only that user’s mail.

  • Pass Authorization or session cookies from the same auth system your API trusts.
  • When mapping API JSON to FivFold types, keep thread ownership consistent with backend user scoping.
  • If you use org-level mailboxes, include tenant context in your API client base URL or headers as you already do elsewhere.

Inspect generated code

Open the scaffolded entities, schemas, or Prisma models for this kit and compare field names (userId, ownerId, etc.) to your User table or IdP subject. Migrate or add FKs where needed—FivFold cannot know your prior schema.

7shadcn/ui primitives

Adding the Email Kit installs these shadcn/ui primitives if not already present:

ComponentUsed in
buttonActions, folder items, compose
inputSearch, compose fields
dropdown-menuLabel picker, actions
cardMessage panel, compose dialog
dialogCompose, reply, forward
scroll-areaThread list, message body, sidebar
labelForm labels in compose
textareaMessage body in compose
accordionMessage headers/body expand
commandRecipient autocomplete
popoverRecipient autocomplete dropdown
badgeLabels, unread count
separatorVisual dividers
tooltipHover hints

Search docs

Search documentation by title or keywords