April 10, 2026 — Branch: feat/meeting-prep-canvas

Canvas Embedding Report

CrayonChat creation flows moved from the copilot modal into the native network canvas. Meeting Prep, Leverage Loops, and Outcomes now have full in-canvas AI experiences — the entire copilot gold standard, embedded where users already work.

3
Canvases Embedded
1,298
Lines Added
7
Files Modified
0
Build Errors

Strategic Context

Per the April 8 meeting with Mark and Jason: the copilot modal is being reduced to meeting prep + general chat only. Outcomes and Leverage Loops creation flows move to the network canvas (middle area). Same CrayonChat generative UI, just rendered in-canvas instead of a modal overlay.

Mark's directive: "Copilot as it IS is the gold standard — bring the entire starter page for each one over." Every component, every animation, every flow from the copilot is preserved in the canvas embedding.

DecisionBeforeAfter
Leverage Loop creation Open copilot modal → switch to leverage mode → PersonPicker → ForkInTheRoad → chat Native in-canvas: PersonPicker + suggested grid → ForkInTheRoad → CrayonChat — all inline
Outcome creation Open copilot modal → switch to outcome mode → ModeStartScreen → chat Native in-canvas: CrayonChat with outcome starters (Raise funding, Hire talent, etc.)
Meeting prep Open copilot modal → meeting mode → select meeting → chat In-canvas CrayonChat (center) + context panel (right side with header, attendees, clickable persons)
Copilot scope 4 modes: chat, leverage, meeting, outcome 2 modes: meeting prep + general chat (leverage/outcomes removed)

Meeting Prep Canvas

Shipped — 4 commits

Full CrayonChat embedded in center canvas

Meeting prep is now a 3-column experience: meeting list (left sidebar), CrayonChat AI conversation (center canvas), and meeting context panel (right side) showing the meeting header, attendees grouped by company, and clickable person rows.

Select meeting Context loads (right panel) Click starter: "Prep for meeting" AI returns goal card Select goal Full meeting prep card

Right-side Context Panel

Consistent with leverage loops and outcomes: the right column shows meeting metadata and attendees. Attendees are clickable — clicking opens the person sheet sidebar (uses master_person_id from classified participant data).

Leverage Loops Canvas

Ready for review

Full copilot leverage flow, now in-canvas

The entire copilot leverage loop creation experience is embedded in the network canvas. When no loop is selected, users see the PersonPicker with a suggested people grid (3x3, sorted by recency). Selecting a person shows ForkInTheRoad: Quick Leverage (instant dispatch) or Interview (CrayonChat conversation).

Creation Flow

PersonPicker search + grid Select person (loads context) ForkInTheRoad Quick Leverage or Interview

Quick Leverage Path

Dispatches immediately via dispatch() API + triggerGeneration(). Shows success animation for 2 seconds, removes dispatched person from grid, returns to picker. New loop appears in sidebar via React Query invalidation.

Interview Path

Opens CrayonChat with person-specific conversation starters (bio-aware: detects fundraising, hiring, etc.). The processMessage callback intercepts the "in every possible way" quick dispatch marker. Supports dispatch_confirmation and interview_card template cards via event listeners.

When Loop IS Selected

Renders existing LeverageLoopsResponseSection with suggestions, trajectories, and actions. No change to the read experience — only the creation flow is new.

Key Components Imported from Copilot

ComponentSourcePurpose
PersonPickercopilot/crayon/person-picker.tsxSearch + select network contacts with context loading
ForkInTheRoadcopilot/crayon/fork-in-the-road.tsxQuick Leverage vs Interview choice screen
Avatarcopilot/crayon/avatar.tsxPerson avatar with fallback initials
LoadingIndicatorcopilot/crayon/loading-indicator.tsxLattice orb animation for thinking state
templatescopilot/crayon/templates.tsCrayonChat template registry (18 card types)
dispatch()copilot/lib/xano-copilot.tsPOST /dispatch → creates suggestion request
triggerGeneration()copilot/lib/xano-copilot.tsPOST /generate-leverage-loop (fire-and-forget)
chat()copilot/lib/xano-copilot.tsPOST /chat with leverage mode context
getNetwork()copilot/lib/xano-copilot.tsGET /network for suggested people grid

Outcomes Canvas

Ready for review

Full copilot outcome flow, now in-canvas

When no outcome is selected, the canvas shows CrayonChat with dynamic outcome conversation starters. Starters adapt based on existing outcomes (offers "Build on X") and network size (mentions total connections and top companies).

Creation Flow

CrayonChat with starters "Raise funding" / "Hire talent" / custom AI interview dispatch_confirmation card dispatch() + triggerGeneration()

Default Starters

Up to 4 dynamic starters: (1) Build on existing outcome (if any active), (2) Leverage network for new goal (with connection count), (3) Raise funding, (4) Hire key talent. Starters are network-aware and adapt to the user's current state.

When Outcome IS Selected

Renders existing OutcomeResponseSection cards with suggestions, trajectories, and actions. Supports individual suggestion selection via URL param. No change to read experience.

Architecture

Three-Column Layout

network.index.tsx ├── grid-cols-[minmax(240px,20%) 1fr minmax(240px,20%)] │ ├── Col 1: SideNav │ ├── teams → TeamsList │ ├── discover → DiscoverList │ ├── leverage-loops → LeverageLoopsList │ ├── outcomes → OutcomesList │ └── meeting-prep → MeetingPrepList │ ├── Col 2: NetworkCanvas │ ├── leverage-loops → LeverageLoopsCanvas (PersonPicker + Fork + CrayonChat) │ ├── outcomes → OutcomesCanvas (CrayonChat with starters) │ └── meeting-prep → MeetingPrepCanvas (CrayonChat only) │ └── Col 3: Right Panel (conditional) ├── leverage-loops → ContextPanel (indigo accent, milestones) ├── outcomes → ContextPanel (purple accent, milestones) ├── meeting-prep → MeetingPrepContextPanel (header + attendees) └── collections → ChatPanel

Data Flow: Dispatch → Sidebar Refresh

User action in canvas CrayonChat │ ├── dispatch({ summary, context: { copilot_mode }, person_id, conversation_history }) │ └── POST /dispatch → returns { suggestion_request_id, status: "submitted" } │ ├── triggerGeneration(suggestion_request_id, mode) │ └── POST /generate-leverage-loop (or /generate-outcome) — fire-and-forget │ └── queryClient.invalidateQueries({ queryKey: ["leverage-loops"] }) // or ["outcomes"] └── React Query refetches → new item appears in sidebar list

Event Flow: Template Card → Dispatch

CrayonChat renders dispatch_confirmation or interview_card template │ ├── User clicks "Confirm" in template card │ └── Card emits CustomEvent("interview-dispatch-ready") │ ├── Canvas useEffect listener catches event │ └── Converts to CustomEvent("inline-dispatch-confirmed") │ └── Second useEffect listener catches confirmed event └── dispatch() + triggerGeneration() + invalidateQueries()

What's Not Changed

The read experience for all three features is untouched:

Commit History

HashMessageScope
aa59126feat(meeting-prep): add meeting prep as 7th canvas viewNew view, list, canvas, search hook, selected hook
370b199feat(meeting-prep): add outcome input + prep CTA buttonChat input, prep flow
eef6f8bfeat(meeting-prep): embed CrayonChat directly in canvasFull CrayonChat with SSE, templates, processMessage
707ee9afeat(meeting-prep): move context to right panel, canvas = full CrayonChatContext panel + clickable attendees
stagedfeat(leverage-loops): embed CrayonChat creation flow in canvasPersonPicker + ForkInTheRoad + dispatch
stagedfeat(outcomes): embed CrayonChat creation flow in canvasCrayonChat with outcome starters + dispatch

Next Steps

Previous Reports

World-Class Polish Pass — April 7–8, 2026 12 waves, 50+ agents, 1,009 files, 48,274 lines Polish Pass Refinement — April 9, 2026 4 waves, 20 agents, 50+ components aligned to copilot visual language

Generated by Claude Code — Orbiter Frontend — April 10, 2026