ForgeSendDocs

Contact Detail Page

Every contact has its own page at /dashboard/all-contacts/{contactId} — reached by clicking a contact's name in the All Contacts grid, in a list's own contact grid, from the View full contact link inside a Pipeline record's detail modal, or from an agency owner's cross-workspace contact search. If the contact doesn't exist, has been soft-deleted, or you're not a member of its workspace, you're redirected straight back to All Contacts rather than shown an error page.

Layout

A fixed tab bar sits above the content — Details, Pipeline, and Activity — with exactly one tab's content showing at a time below it. The tab bar itself never scrolls; each tab owns its own bounded region that scrolls internally on its own when it needs to, so a long list in one tab never grows the page itself.

  • Details combines Contact details, Company details, and Custom fields into one continuous multi-column grid — one column on a narrow screen, two from a small breakpoint up, three on a large one — separated by plain section-label dividers rather than separate cards.
  • Pipeline shows this contact's Pipeline records as a single internally-scrolling list.
  • Activity splits into two independent columns side by side — Activity timeline on the left, Campaign history on the right — each scrolling within its own bounded area.

Contact and company details

The Details tab lays out Contact details and Company details as two groups inside one continuous grid — not two separate cards. A plain section-label divider (an icon, a label, a thin rule underneath) separates the groups; there's nothing to click on it, since a tab already replaced the old expand/collapse interaction.

Details tab — read only
👤Contact details

First name

Dana

Last name

Okafor

Email

dana@nimbusrobotics.co

Verification status

Valid

Title

VP Operations

Location

Austin, TX

🏢Company details

Company

Nimbus Robotics

Company Headcount

51-200

Founded Year

2018

Company Domain

nimbusrobotics.co

Company Industry

Logistics

HQ City

Austin

Contact details — First name, Last name, Email, Verification status (Unverified / Valid / Risky / Invalid / Verified / High probability / Catch-all / Email not found), Title, Seniority, Job Function, LinkedIn URL, Location. Every field is click-to-edit; clicking Email shows the raw address, saving lower-cases and trims it, and rejects a duplicate already in this workspace or an attempt to clear it to empty. Location is one field on screen but writes to two underlying columns behind the scenes — typing "Austin, TX" splits on the comma into city and region; typing a single value with no comma saves it as one broad location string instead.

Company details — Company, Company Headcount, Company Specialties, Founded Year, and Company Description are all click-to-edit. Company Headcount accepts either a plain whole number or a range string like "51-200" — whichever you type is what's saved; the other representation is cleared. Company Domain, Company Industry, Company Type, HQ City, HQ Region, and HQ Country are read-only — there's no edit control for any of these six anywhere in the app today, on this page or the All Contacts grid; they're populated only by enrichment or import.

Other custom fields

A third section-label group, Custom fields, sits at the bottom of the same Details-tab grid, in its own full-width row below Contact details and Company details — not a separate card, and nothing to expand or collapse.

Details tab — read only
{}Custom fields

Anything not covered above (JSON)

{"referralSource":"partner-webinar"}

Every key in the contact's custom-fields data that isn't one of the ~18 known fields shown above (typically an unexpected column from a CSV import) shows up here as a single-line, minified JSON blob — one editable field, not a formatted key/value editor. Editing merges by key: a key you leave out of what you type is left untouched; setting a key to null clears it.

Activity timeline

The Activity tab — one of three tabs at the top of the page, alongside Details and Pipeline — shows a merged, chronological feed of everything real that's happened with this contact: email opens, clicks, and bounces; Pipeline stage changes; and reply messages, both received and sent. It sits side by side with Campaign history as two independent columns within that same tab.

Activity tab — Timeline — read only

Timeline

💬

Replied: "Re: Quick question about your Q3 hiring plans"

ReplySep 2, 2026, 3:14 PM
✉

Clicked a link in an email

EmailSep 1, 2026, 11:02 AM
📈

Moved from Engaged to Interested

PipelineAug 30, 2026, 9:47 AM
✉

Opened an email

EmailAug 28, 2026, 8:15 AM

Each entry gets a small colored icon badge by source — a Mail icon in #00C896 for email opens, clicks, and bounces; a TrendingUp icon in #F59E0B for Pipeline stage changes; and a MessageSquare icon in #60A5FA for reply messages — plus a matching colored label (Email / Pipeline / Reply) and a timestamp, newest entry first.

A contact with no recorded activity yet shows a plain centered message, "No activity recorded for this contact yet." — not an error state, not a stuck loading spinner.

When this contact's own data shows direct evidence that a reply lost its link to a campaign lead after being received, a plain line appears above the list: "Reply history may be incomplete for this contact." This is a real, computed, per-contact signal, not a blanket disclaimer shown to everyone — it only appears when that specific evidence exists for this particular contact.

Pipeline records

Reached via the Pipeline tab — the second of the page's three tabs. Its content is a single, internally-scrolling list, not a standalone card on the page — a long list scrolls within the tab's own bounded area, never the page itself.

Pipeline tab — read only
DetailsPipelineActivity

Q3 warehouse automation outreach

Meeting Requested$34,000
91›

Spring re-engagement

Active
67›

Every Pipeline record this contact holds — one per campaign they're enrolled in — with the campaign name, a stage badge, the estimated value if set, and the health score. Clicking a row opens the same record detail modal used everywhere else in Pipeline, where you can change stage, set an estimated value, and review or undo history. A contact enrolled in no campaign yet shows "Not in any campaign's pipeline yet." instead of an empty list.

Campaign history

Reached via the Activity tab, where it sits side by side with Activity timeline as two independent columns — not a standalone card, and not collapsed by default in the old accordion sense, since there's nothing to expand: both columns are visible together as soon as you open the tab, each scrolling within its own bounded area.

Activity tab — read only

Timeline

💬

Replied: "Re: Quick question…"

✉

Clicked a link in an email

Campaign history

Q3 warehouse automation outreach

ACTIVE

Spring re-engagement

PAUSED

Every campaign this contact is enrolled in, with the campaign name and its raw status badge (ACTIVE, PAUSED, DRAFT, or ARCHIVED) — a read-only list, with no click-through from a row itself.

Editing and the manual-edit rule

Every edit here goes through the same click-to-edit control the All Contacts grid uses — click, edit, save on blur or Enter, revert on Escape or on a failed save. Saving marks each field you touched as manually edited, timestamped — the same rule the All Contacts grid already follows: a human's own edit always wins. A later automated write to that same field, from a fresh CSV import or a new enrichment run, won't silently overwrite what you typed here. Deliberately clearing a field to blank bypasses that protection, since a human clearing something on purpose isn't the scenario the rule exists to guard against.

Where tagging, deleting, and list actions live

Tagging, deleting, and adding to a list or campaign all live on the All Contacts grid's own bulk-selection bar instead of here — none of the three has its own control on this single-contact page yet.

Where to go next

Next: Lists & Contacts overview