Desktop email, reimagined

See your inbox as a
conversation graph.

Every thread is a flat, confusing wall of quoted replies. NodeMail draws it the way it actually happened — each message a node on a timeline, a lane for every person, edges showing who replied to whom and the exact moment each contact joined the chain.

  • Gmail & IMAP
  • Local-first & private
  • macOS · Windows · Linux
NodeMail — “Q3 launch plan” live demo

Tip: click any message node →

A real, interactive recreation of NodeMail’s thread graph. Click nodes, flip the layout, switch the accent.

One client for every account you have —

✉️ Gmail 🌐 IMAP / SMTP 📇 Contacts 📅 Google Calendar 🔒 Local-first
Why a graph

Threads hide the conversation. Graphs reveal it.

A reply list flattens a branching, multi-person discussion into one scroll. You lose the branches, you lose who answered whom, and you can’t see when someone was looped in. NodeMail keeps the shape.

Every other client
Maya Okonkwo

Q3 launch plan 🚀

Theo Park

Re: Q3 launch plan

Priya Shah

Re: Q3 launch plan

Sam Rivera

Re: Q3 launch plan

Theo Park

Re: Q3 launch plan

Maya Okonkwo

Re: Q3 launch plan

Who replied to Priya? When did Sam join? You can’t tell.

NodeMail

Branches, replies and the moment each person entered — at a glance.

The signature view

A timeline that thinks in people, not just dates.

NodeMail lays each conversation along a time axis and gives every participant their own lane. The result is a map you can read in a second: the spine of the discussion, the replies that branched off it, and the precise point where each new person was pulled in.

  • ①
    A lane per person. Lanes are ordered by who appeared first, so newcomers always enter from a fresh track.
  • ↳
    Edges that mean something. NodeMail resolves real reply structure — In-Reply-To → References → chronological fallback — so the tree is correct even when a client mangles the headers.
  • ●
    Unread, at a glance. Unread nodes glow in their lane’s color; clusters fold repeated bursts into a single badge you can expand.
  • ⤢
    Your axis, your zoom. Flip the chain horizontal or vertical, zoom, pan, and click any node to open it in the reading pane.
Try it on your own inbox →
How NodeMail draws an edge
  1. 1
    Has an In-Reply-To header?

    Link straight to that exact message. Most replies land here.

    reply
  2. 2
    Only a References chain?

    Walk the chain and attach to the nearest known ancestor.

    reply
  3. 3
    No threading headers at all?

    Reconnect chronologically so the chain never breaks — shown as a dashed “reconnected” edge.

    reconnected

A parent is always older than its replies — the timeline can’t lie.

Everything you’d expect — and the graph you didn’t

A full email client, end to end.

NodeMail isn’t a toy. It syncs, reads, writes, files, searches and keeps your contacts and calendar — all wrapped around the conversation graph.

The conversation graph

The signature view: messages as nodes, a lane per person, animated reply edges, and a separate per-contact graph of everything you’ve exchanged with someone.

Unlimited accounts

Add as many Gmail and IMAP accounts as you like, each with its own avatar and color. Drag to reorder, or merge them all into one unified “All inboxes”.

Address book

One searchable list that merges your Google Contacts, the people you actually email, and entries you add yourself — with avatars, phones, orgs and notes. Bulk-edit and delete.

Calendar

Google Calendar in agenda, week and month views. Toggle calendars on and off, expand recurring series, and create, edit or delete events — without leaving your mail.

Safe reading pane

HTML is sanitized with DOMPurify — no scripts, forms or tracking pixels. Remote images are blocked by default; load them once, or trust a sender to load them always.

Compose, reply, forward

Reply, reply-all and forward with correct In-Reply-To and References threading, so your sent message snaps right back into the graph where it belongs.

Folders & labels

Inbox, Sent, Drafts, Trash, Spam, Starred and your own labels — each with live unread counts and a custom emoji icon you pick yourself.

Instant + deep search

Filter your cached mail as you type — subjects, snippets, bodies and people. Press enter to push the query to the server (Gmail q: operators or IMAP SEARCH) for everything else.

Make it yours

Accent color, text color, interface scale, four font families, gradient / solid / image / daily-Bing backgrounds, plus graph edge style and node radius — all live, all local.

Private by construction

Your mail stays on your machine.

NodeMail has no server of its own. It talks only to your email provider and caches everything locally. There’s no account to create, no analytics phoning home, nothing about your mail leaves your computer.

See the architecture →
🗄️

Local-first cache

Threads, messages, contacts and calendar live in a local SQLite database — never in anyone’s cloud but your provider’s.

🔑

Keychain tokens

OAuth tokens and IMAP passwords are encrypted in your OS keychain via Electron safeStorage.

🛡️

Hardened renderer

Context isolation on, Node integration off, full sandbox. The UI can’t touch the network or disk directly.

🧼

No trackers

Mail HTML is scrubbed and remote images gated, so tracking pixels never tell a sender you opened their email.

Make it yours — try it right here

Deep customization, live.

Every control below re-themes this whole page in real time — the same engine that themes the app. Pick an accent, a font, a backdrop, and reshape the graph nodes.

⤺ Everything is saved to your machine and applied instantly — no server, no round-trip.

Under the hood

Built provider-agnostic, from day one.

A clean split keeps the privileged work in the main process and the UI dumb about providers. Add a mail backend behind one interface and the graph just works.

renderer · React 19

The UI you see. Talks only to a narrow, typed window.api — no Node, no network, fully sandboxed.

preload · contextBridge
typed IPC contract
main · Node

All the real work: OAuth, the Gmail & IMAP providers, the sync engine, local SQLite, token storage.

Gmail IMAP / SMTP POP3 soon Microsoft soon
Electron React 19 TypeScript React Flow + elkjs SQLite (sql.js) Tailwind CSS
Get started

Two ways to connect your account

NodeMail is local-first and talks to your mailbox with your own credentials — nothing routes through us. Connect Gmail with Google sign-in for the richest integration, or connect Gmail (or any other provider) over standard IMAP/SMTP. Either way, credentials are stored encrypted on your device.

Option A · Gmail — Google sign-in

The deepest integration: the official Gmail API gives fast delta sync, native labels and contacts. A one-time, few-minute setup of your own Google Cloud OAuth client.

  1. 1

    Create a Google Cloud project

    Open the Google Cloud Console and create a new project (or select an existing one).

  2. 2

    Enable the APIs

    Under APIs & Services → Library, enable the Gmail API, People API (contacts) and Google Calendar API.

  3. 3

    Configure the consent screen

    In OAuth consent screen, choose External, fill in the basics, and add your own Google address under Test users. While the app stays in “testing” you don't need Google verification.

  4. 4

    Create a “Desktop app” OAuth client

    Go to Credentials → Create credentials → OAuth client ID and pick application type Desktop app. Copy the generated Client ID and Client secret.

  5. 5

    Paste them into NodeMail

    On NodeMail's connect screen, paste the Client ID and secret, then Connect Gmail. They're stored encrypted on your device and never leave it.

Option B · Any provider — IMAP / SMTP

No Google Cloud project required. Works with Gmail, Fastmail, Yahoo, iCloud, Outlook or any custom host — one-click presets fill in the server settings for you.

  1. 1

    Choose IMAP, then pick your provider

    On NodeMail's connect screen switch to IMAP and tap a preset — Gmail, Fastmail, Yahoo, iCloud or Outlook — to fill the hosts and ports automatically. For anything else, type the IMAP and SMTP host yourself (see the table below).

  2. 2

    Generate an app password

    Providers with two-factor sign-in — Gmail, Yahoo, iCloud (and Fastmail) — need a generated app password, not your normal login password. For Gmail, create one here (2-Step Verification must be on) and enable IMAP in your Gmail settings.

  3. 3

    Enter your details and connect

    Fill in your email address and that password, confirm the IMAP port (993) and SMTP port (465 for implicit TLS, or 587 for STARTTLS), then Connect. Everything is stored encrypted on your device.

ProviderIMAP host · portSMTP host · port
Gmailimap.gmail.com · 993smtp.gmail.com · 465
Fastmailimap.fastmail.com · 993smtp.fastmail.com · 465
Yahooimap.mail.yahoo.com · 993smtp.mail.yahoo.com · 465
iCloudimap.mail.me.com · 993smtp.mail.me.com · 587
Outlookoutlook.office365.com · 993smtp.office365.com · 587

Why your own credentials? Whichever route you pick, your mail stays in your account and on your own quota — NodeMail is just a local client. Google requires a client secret even for desktop apps and ties API quota & verification to the project that owns it, so option A uses your own; option B uses your provider's standard IMAP/SMTP. More on privacy →

Get NodeMail

Stop scrolling threads. Start reading conversations.

A free, local-first desktop email client for macOS, Windows and Linux. Connect a Gmail or IMAP account and watch your first thread unfold as a graph.

Prefer to build it yourself? Clone the repo and run npm run build.