Pipeline Overview
Trends ({{ trends.currentMonth }} vs {{ trends.previousMonth }})
Monthly Active Investors
Unique investors who actually replied per month — met, followed up, circled back, invested, or passed (not just sent or introduced)
Unique Firms That Took an Intro ({{ uniqueFirms[uniqueFirmsPeriod]?.count || 0 }})
{{ (uniqueFirms[uniqueFirmsPeriod]?.firms || []).map(f => f.isAngel ? `${f.firm} (${f.investorCount})` : f.firm).join(', ') }}
My Follow-ups
Pipeline by Status
Overdue Follow-ups
| Founder | Node | Investor | Status | Due Date |
|---|---|---|---|---|
| {{ req.founder?.name }} | {{ req.node?.name }} | {{ req.investor?.name }} | {{ formatStatus(req.status) }} | {{ req.nextFollowupDate }} |
Portfolio
My Portfolio
| Company | Investment Date | Equity % | Valuation | Markup | Paper Value | Status | Actions |
|---|---|---|---|---|---|---|---|
|
{{ company.founder?.companyName }}
{{ company.oneLiner }}
{{ company.notes }}
{{ company.founder?.name }}
|
{{ company.investmentDate || '-' }} | {{ company.equityPercent ? company.equityPercent + '%' : '-' }} | {{ formatCurrency(company.currentValuation) }} | {{ markupLabel(company) }} | {{ formatCurrency(calculatePaperValue(company)) }} |
A
E
P
C
({{ getCompletionStatus(company) }}/4)
|
🧠 Study the network
Spaced-repetition flashcards over your VIP investors. Fill in the blanks as you go — it makes matching sharper.
All caught up on your VIP investors.
Cards come back on a spaced schedule — check in tomorrow.
What's their focus, geography, and check size?
Saved ✓
Broadcast to Portfolio Founders
Variables: {{firstName}}, {{name}}, {{companyName}}.
Plain text — line breaks and links are preserved.
Recipients
Defaults to founders who've signed their advisory agreement. Uncheck anyone to leave them off.
Event Invites
Pick who each upcoming event is for. Founders at those stages are proposed below every hour (at most 2 a week per person, never anyone already on the event). Nothing is sent until you approve it.
| {{ r.name || r.email }} {{ r.email }} |
{{ r.audience }} | {{ r.message }} {{ r.error }} |
Trials
Intro requests go out two at a time until one investor says yes (at most 10). Then the trial pauses and they have a week to sign.
Asking investors — the draft board sends {{ t.batchSize }} at a time and pauses at the first yes.
First yes {{ (t.firstYesAt || '').split('T')[0] }} — intro requests are paused. Follow up to sign by {{ (t.decideBy || '').split('T')[0] }}.
{{ t.requestCap }} requests, no yes. Nothing more goes out — talk to them, then pass or keep going by hand.
The week to sign ran out.
Founder Onboarding
| Company | Founder | Terms | Status | Last Updated | Actions |
|---|---|---|---|---|---|
|
{{ workflow.portfolioCompany?.founder?.companyName }}
{{ workflow.entityName }}
|
{{ workflow.portfolioCompany?.founder?.name }} |
{{ workflow.offerEquityPercent }}%
{{ formatVestingSchedule(workflow.vestingMonths, workflow.vestingCliffMonths) }}
|
{{ formatOnboardingStatus(workflow.status) }}
⏳ Stalled {{ formatStallAge(workflow.stall.hoursSince) }} — {{ workflow.stall.waitingOn }}
|
{{ workflow.updatedAt?.split('T')[0] }} |
|
Start Onboarding
Standard advisory: 4-year vest, no cliff
{{ workflowDetails.workflow?.portfolioCompany?.founder?.companyName }}
{{ workflowDetails.workflow?.portfolioCompany?.founder?.name }}
Progress
83(b) Elections
{{ e83bInfo.daysRemaining == null ? '—' : e83bInfo.daysRemaining < 0 ? ('OVERDUE ' + (-e83bInfo.daysRemaining) + 'd') : (e83bInfo.daysRemaining + 'd left') }}Set MATCAP_83B_ENTITY_* and MATCAP_83B_PERSONAL_* secrets to enable both elections.
Incorporation Status
Share Details
✓ Room for MatCap ✕ No room — needs more authorized shares Issued shares unknownOnly {{ workflowDetails.shareDetails.availableShares?.toLocaleString() }} shares are unissued, but MatCap needs {{ workflowDetails.shareDetails.shareCount?.toLocaleString() }}. The company would need to authorize more shares before it can issue MatCap.
We couldn't find issued shares in the formation docs. Enter it below to check whether there's room.
Board Consent Record
Written consent in lieu of a board meeting to approve equity issuance.
Formation docs — backup copies (stored in DB)
Skips the guided flow — use to drive onboarding by hand or unstick a workflow.
Founders
{{ filteredFounders.length }} shown| Name | Company | Location | Stage | Round Status | Actions | |
|---|---|---|---|---|---|---|
|
{{ founder.name }}
(hidden)
{{ cat.name }}
|
{{ founder.email }} | {{ founder.companyName }} | {{ [founder.city, countryName(founder.country)].filter(Boolean).join(', ') || '-' }} | {{ formatStage(founder.companyStage) }} | {{ formatRoundStatus(founder.roundStatus) }} |
Nodes (Connectors)
{{ node.name }}
{{ node.email }}
{{ node.company }}{{ node.company && node.role ? ' • ' : '' }}{{ node.role }}
Investors
Bulk Research Progress
| # | Investor | Firm | Sectors | City | Sent | Yes | Pass | Ignored | Rate | Last request sent |
|---|---|---|---|---|---|---|---|---|---|---|
| {{ leaderboardRankLabel(idx) }} | {{ item.name }} ★ | {{ item.firm || '—' }} | {{ (item.categories || []).filter(c => c.type === 'sector').map(c => c.name).slice(0, 3).join(', ') || '—' }} | {{ item.city || '—' }} | {{ item.introTotal || 0 }} | {{ item.introAccepted || 0 }} | {{ item.introPassed || 0 }} | {{ item.introIgnored || 0 }} | {{ item.acceptRate != null ? item.acceptRate + '%' : '—' }} | {{ item.lastIntroAt ? formatRelative(item.lastIntroAt) : '—' }} |
| Thesis: {{ item.research.investmentThesis }} · Founder fit: {{ item.research.founderPreferences }} | ||||||||||
| No investors meet the ≥{{ investorMinIntros }} intros bar. Lower the threshold to widen the field. | ||||||||||
{{ item.name || item.investor?.name }}
★ VIP Inactive AI Researched Sectors Stage Strong connection Stage fit Thesis match Sector match Founder fit Active 1st-time friendly Stale ({{ item.weeksSinceContact }}w){{ item.firm || item.investor?.firm }} {{ (item.role || item.investor?.role) ? '• ' + (item.role || item.investor?.role) : '' }}
{{ [item.city || item.investor?.city, countryName(item.country || item.investor?.country)].filter(Boolean).join(', ') }}
Check: {{ item.checkSize || item.investor?.checkSize }}
{{ item.acceptRate ?? item.investor?.acceptRate }}% accept · {{ item.introAccepted ?? item.investor?.introAccepted }} / {{ item.introTotal ?? item.investor?.introTotal }} intros
via {{ item.nodeConnection.nodeName }} ({{ item.nodeConnection.strength }})
Discover Investors
Agent-sourced active pre-seed/seed first-check investors (web search). Review and approve to add them to your network. Runs daily; or run now.
Intro Requests
Agent autonomy
Kill switches for what the agent does without you. Defaults to off.
Replies needing you
Investor replied with something the classifier couldn't safely auto-handle. Read, then mark passed / introduced / circle-back yourself.
| Founder | Node | Investor | Score | Status | Requested | Next Follow-up | Actions |
|---|---|---|---|---|---|---|---|
| {{ req.founder?.name }} | {{ req.node?.name }} | @ {{ req.investor?.firm }} (no email) | {{ req.matchScore }} — |
{{ formatStatus(req.status) }}
⏳ {{ formatScheduledSend(req.scheduledSendAt) }}
{{ sendState(req).t }}
|
{{ req.dateRequested }} | {{ req.nextFollowupDate || '-' }} | Queued for {{ formatScheduledSend(req.scheduledSendAt) }} 📧 Open draft |
Manage Relationships
Founder-Node Relationships
Node-Investor Connections
Inbound Intro Logs
Emails received via BCC. Review and confirm to log intro requests.
Brands
| Brand | Contact | Status | Notes | Actions |
|---|---|---|---|---|
|
{{ brand.name }}
|
{{ brand.contactName }}
{{ brand.contactEmail }}
--
|
{{ brand.notes || '--' }} |
|
Founder Leaderboard
| # | Founder | Company | Stage | Total Sent | Introduced | Passed | Ignored | Pending | Accept Rate | |
|---|---|---|---|---|---|---|---|---|---|---|
| {{ idx + 1 }} | {{ row.name }} | {{ row.companyName }} | {{ formatStage(row.companyStage) }} | {{ row.totalSent }} | {{ row.introduced }} | {{ row.passed }} | {{ row.ignored }} | {{ row.pending }} | {{ row.acceptRate }}% |
Network Health
Dormancy Breakdown
| Investor {{ healthSort.dir === 'asc' ? '▲' : '▼' }} | Intros {{ healthSort.dir === 'asc' ? '▲' : '▼' }} | Response {{ healthSort.dir === 'asc' ? '▲' : '▼' }} | Meetings {{ healthSort.dir === 'asc' ? '▲' : '▼' }} | Last Intro | Status {{ healthSort.dir === 'asc' ? '▲' : '▼' }} | Actions |
|---|---|---|---|---|---|---|
|
{{ inv.name }}
{{ inv.firm }}
|
{{ inv.totalIntros }} total
{{ inv.responded }} responded, {{ inv.ignored }} ignored
|
|
{{ inv.meetings }} meetings ({{ inv.invested }} invested) |
{{ inv.lastIntroDate }}
{{ inv.daysSinceLastIntro }} days ago
Never
|
Inactive {{ dormancyReasonLabel(inv.dormancyReason) }} Healthy |
Founder Pipeline Health
| Founder | Categories | Target | This Week | Rate | Status | Network | Actions |
|---|---|---|---|---|---|---|---|
|
{{ row.founder.name }}
{{ row.founder.companyName }}
|
{{ cat.name }}
none
|
/wk
{{ row.cadence.why }}
|
{{ row.introsThisWeek }} (last: {{ row.introsLastWeek }}) | {{ row.weeklyRate }}/wk | {{ row.status }} |
{{ row.activeIntros }} active, {{ row.pendingResponse }} pending
|
Network Availability: {{ networkAvailability.founder.name }} ({{ networkAvailability.founder.companyName }})
| {{ inv.name }} | {{ inv.firm }} | {{ cat }} | {{ formatStatus(inv.status) }} Available No category match |
Marketplace Health
Throughput
% of generalist investors stale (≥3 weeks since contact). Specialty firms excluded — they have legitimate gaps.
| Name | Firm | Weeks since contact |
|---|---|---|
| {{ item.name }} | {{ item.firm || '—' }} | {{ item.weeksSinceContact }}w |
Stale open investors
Active, not on cooldown, not dormant — and ≥3 weeks since contact. Includes generalists + specialists.
| Name | Firm | Last contact | Weeks |
|---|---|---|---|
| {{ item.name }} | {{ item.firm || '—' }} | {{ item.lastContactDate || 'never' }} | {{ item.weeksSinceContact }}w |
Investors to review — possibly disengaged
Last 2 intros (≥4w old) both stalled with followups sent. May be parental leave / fund cycle / just done with us — you decide.
| Investor | Firm | Last 2 stalled intros | Action |
|---|---|---|---|
| {{ item.name }} | {{ item.firm || '—' }} |
{{ si.founderName || `Founder #${si.founderId}` }} ·
{{ si.status }} ·
{{ si.bumpCount }} bump{{ si.bumpCount === 1 ? '' : 's' }} ·
{{ si.ageWeeks }}w ago
|
Untagged investors ({{ untaggedInvestors.count }})
Connected to a node, active, but missing sector tags — silently excluded from matching. Tag them to bring them into the pool.
| Investor | Firm | Tags | |
|---|---|---|---|
| {{ inv.name }} | {{ inv.firm || '—' }} | none {{ inv.tagCount }} (no sector) |
Supply / Demand by Sector
Weekly capacity model. Demand = founders × their per-week target. Supply = investors × (1 intro / 3 weeks). Ratio >1.3 = under-supplied (recruit investors), <0.7 = over-supplied (recruit founders). Generalists are sized against all founders; specialists against their own sector.
| Sector | Founders | Investors | Demand /wk | Supply /wk | Ratio | Status | What to do |
|---|---|---|---|---|---|---|---|
| {{ row.sectorName }} (all founders) | {{ row.founders }} | {{ row.investors }} | {{ row.weeklyDemand }} | {{ row.weeklySupply }} | {{ row.ratio !== null ? row.ratio : '—' }} | {{ {undersupplied:'Under-supplied', balanced:'Balanced', oversupplied:'Over-supplied', dormant:'Dormant'}[row.status] }} | {{ row.actionHint }} |
| No sector data — add categories first. | |||||||
Investor Utilization
| Investor | Firm | Intros (90d) | Reliability | Sectors | Status |
|---|---|---|---|---|---|
| {{ inv.name }} | {{ inv.firm || '—' }} | {{ inv.introsLast90Days }} |
|
{{ sector }} Generalist |
{{ inv.utilizationStatus === 'over' ? 'Over-utilized' : inv.utilizationStatus === 'under' ? 'Under-utilized' : inv.utilizationStatus === 'cooldown' ? 'Cooldown' : inv.utilizationStatus === 'dormant' ? 'Dormant' : 'Normal' }}
{{ inv.cooldownReason }}
|
| No investors match filter | |||||
Coverage Gaps
| # | Founder | Company | Heat Score | Reason |
|---|---|---|---|---|
| {{ f.waitlistPosition }} | {{ f.name }} | {{ f.companyName || '—' }} |
|
{{ f.reason }} |
Founder Waitlist
{{ marketplaceHealth.waitlist.total }} founder{{ marketplaceHealth.waitlist.total !== 1 ? 's' : '' }} in sectors with insufficient investor coverage, ranked by heat score.
| # | Founder | Company | Heat Score | Sectors | Gap Sectors |
|---|---|---|---|---|---|
| {{ f.waitlistPosition }} | {{ f.name }} | {{ f.companyName || '—' }} |
|
{{ s }} | {{ g }} |
Algo Report Card
Does the match score predict anything? Grades every reviewed suggestion against what actually happened. Read-only — nothing here changes the algorithm.
{{ layer.title }}
{{ algoVerdictLabel(layer.data.verdict) }}{{ layer.subtitle }}
{{ layer.data.verdictDetail }}
If the top third and bottom third land on the same number, the score isn't sorting anything.
What's actually predicting
Lift = this feature's rate minus the overall baseline. A weight in computeFitScore
that shows ~0 lift is buying you nothing; a negative lift means it's pointing the wrong way.
| Feature | Reviewed | Approval | Approval lift | Decided | Accept | Accept lift |
|---|---|---|---|---|---|---|
| {{ f.feature }} thin | {{ f.reviewed }} | {{ algoPct(f.approvalRate) }} | {{ algoLift(f.approvalLift) }} | {{ f.decided }} | {{ algoPct(f.acceptRate) }} | {{ algoLift(f.acceptLift) }} |
Why you rejected ({{ algoReport.rejections.total }})
{{ algoReport.rejections.fixable }} fixable — stale tags, not bad scoring. Each is a one-click correction that stops the suggestion coming back.
Training-data hygiene
Share of rejects that carry a reason the system can learn from. "Other" and "Not a fit (gut)" teach it nothing.
Cooldown misses
Times you rejected a suggestion because the investor had already been sent a deal too recently. These never count against the investor or the founder — they're a verdict on our own pacing.
{{ algoReport.systemMisses.diagnosis }}
Never-suggest-again list ({{ matchBlocks.total }})
Pairs you permanently blocked from the reject modal. Everything else you reject stays re-suggestable — a pass today is often a fit next quarter. {{ matchBlocks.globalCount }} of these are blocked for every founder.
| Investor | Scope | Reason | Blocked | |
|---|---|---|---|---|
| {{ b.investorName || ('Investor #' + b.investorId) }} · {{ b.investorFirm }} | All founders {{ b.founderName || ('Founder #' + b.founderId) }} | {{ b.reason || '—' }} ({{ b.rejectionCategory }}) | {{ (b.createdAt || '').slice(0, 10) }} |
| Band | n | Rate | Lift |
|---|---|---|---|
| {{ b.label }} | {{ b.n }} | {{ algoPct(b.rate) }} | {{ algoLift(b.lift) }} |
Category Manager
Add Category
{{ typeGroup.type }}
{{ typeGroup.description }}
| {{ cat.name }} | {{ editingCategoryId === cat.id ? editCategoryForm.name || cat.name : cat.name }} | {{ cat.color }} |
Sectors
Industry focus areas
AI Agent
Everything the AI worker has done or proposed. Approve proposals to let them take effect.
| When | Agent | Action | Status | Review |
|---|---|---|---|---|
| {{ (a.createdAt || '').replace('T',' ').slice(0,16) }} | {{ a.agent }} |
{{ a.summary }}
{{ a.actionType }}· dry-run
{{ a.reasoning }}
|
{{ a.status }} | {{ a.decidedBy }} |
| No agent actions {{ agentFilter !== 'all' ? "with status '" + agentFilter + "'" : 'yet' }}. | ||||
Calls
Every transcript founders have sent us — real investor meetings from the portal/Granola, and Pitch Gym practice reps — with the AI read on each.
The read
{{ callDetail[callKey(call)].summary }}
{{ callDetail[callKey(call)].summary }}
Transcript
{{ callDetail[callKey(call)].transcript }}
Directory
Every person we've touched — founders, signups, leads, and anyone who's used a lead-magnet tool.
Exports the {{ hasDirectoryFilters ? 'filtered' : 'full' }} list. People & leads only (not investors), no unsubscribe suppression — for your own list-building, not blind cold sends.
| Name | Company | City | Sources | Tags | Last touch | |
|---|---|---|---|---|---|---|
| {{ row.name || '—' }} | {{ row.email }} | {{ row.company || '—' }} | {{ row.city || '—' }} | {{ directorySourceLabel(s) }} | {{ t }} — | {{ directoryFormatRelative(row.lastTouchAt) }} |
Edit details
Overrides appliedTags
Source records
{{ JSON.stringify(src.data, null, 2) }}
Applications
| Founder | Company | Sector | Links | Applied | Status | Actions |
|---|---|---|---|---|---|---|
|
{{ app.user?.firstName }} {{ app.user?.lastName }}
{{ app.user?.email }}
{{ app.user?.city }}
|
{{ app.companyName }}
{{ app.oneLiner }}
{{ app.url }}
✨ Investor blurb{{ app.blurb.investorBlurb }}
🤖 {{ app.aiScore }}/10 · {{ app.aiRecommendation }}
{{ app.aiReasoning }}
your note: {{ app.decisionReason }}
|
{{ app.sector }} |
LinkedIn
@{{ app.user.twitterHandle }}
via {{ app.user.source }}
|
{{ app.appliedAt?.split('T')[0] }} | ⏳ researching {{ app.applicationStatus }} |
{{ app._aiInvite.emailed ? '🎙️ Interview sent ✓' : '🎙️ Invite ready' }}
--
|
Voice Interview AnswersQ{{ qi + 1 }}: {{ q.question }} {{ q.reason }} Duration: {{ Math.floor(getAnswer(app, qi).durationSeconds / 60) }}:{{ (getAnswer(app, qi).durationSeconds % 60).toString().padStart(2, '0') }} No answer recorded |
||||||
| Name | Role | One-liner | City | Status | Signed Up | Actions | |
|---|---|---|---|---|---|---|---|
|
{{ signup.firstName }} {{ signup.lastName }}
LinkedIn
|
{{ signup.email }} | {{ signup.role || 'unknown' }} | {{ signup.oneLiner }} | {{ signup.city }} | {{ signup.status }} | {{ signup.createdAt?.split('T')[0] }} |
|
| No signups found. | |||||||