GTM Studio Product Clarity: First Call Deck vs AI Presentation¶
Date: 2026-03-08
Context: Aligns to PARTNER_OUTPUT_PORTABILITY_AUDIT.md
Status: Product strategy recommendation — pending decision
The Problem¶
Two menu items point to what is architecturally the same engine:
| Route | Nav Label | What It Does |
|---|---|---|
/dashboard/user/first-call-deck |
First Call Deck | Wizard: company name/URL → internet enrichment → 8-slide deck |
/dashboard/user/ai-presentation |
AI Presentation | Template picker: 17+ templates → fill form → multi-format GTM content |
Both generate GTM content via the same pipeline (GtmContentSchema, AWS Bedrock Claude, ContentFormatter). First Call Deck is literally FirstCallDeckTemplate extending PresentationTemplate inside the AiPresentation extension.
A user asking "Where do I input what I'm trying to sell to a company?" could reasonably go to either place. That's the clarity failure.
Current Architecture (Fact)¶
app/Extensions/AiPresentation/
├── System/
│ ├── Templates/
│ │ ├── PresentationTemplate.php ← abstract base
│ │ ├── FirstCallDeckTemplate.php ← FCD is ONE template
│ │ ├── AwsMarketplaceListingTemplate.php
│ │ ├── ValuePropositionTemplate.php
│ │ ├── CoSellBriefTemplate.php
│ │ └── ... (17 total)
│ ├── Schema/
│ │ ├── GtmContentSchema.php ← shared output schema (v1.2)
│ │ └── FirstCallEnrichmentSchema.php ← enrichment-specific schema (v1.0)
│ ├── Services/
│ │ ├── FirstCallEnrichmentService.php ← web scrape → Claude synthesis
│ │ ├── ContentFirstGenerationService.php ← shared generation
│ │ ├── ContentFormatter.php ← shared output (MD, HTML, PDF)
│ │ ├── DryRunService.php ← shared dry-run
│ │ └── ...
│ └── Http/Controllers/
│ ├── AiPresentationController.php ← handles both FCD + templates
│ └── AbTestingController.php ← A/B testing for listings
│
├── Livewire/
│ └── FirstCallDeckWizard.php ← dedicated wizard UI
Key insight: FCD adds exactly ONE unique capability — the internet enrichment pipeline (FirstCallEnrichmentService + Serper API). Everything else (generation, output formats, dry-runs, gallery) is shared infrastructure.
The Overlap Matrix¶
| Capability | First Call Deck | GTM Studio | Verdict |
|---|---|---|---|
| Internet enrichment (company research) | Yes | No | FCD's only unique feature |
| AI content generation | Yes | Yes | Same engine |
| Multi-format output (MD, HTML, PDF, PPTX) | Yes | Yes | Same ContentFormatter |
| Dry-run buyer personas | No | Yes | GTM Studio only |
| A/B testing | No | Yes | GTM Studio only |
| Gallery / asset management | No | Yes | GTM Studio only |
| Deck upload + analysis | No | Yes | GTM Studio only |
| Brand voice integration | Yes | Yes | Same BrandContextBuilder |
| MCP/Agent readiness | A/A | A/A | Both via schemas |
| Pre-onboarding (no KB required) | Yes | Yes* | *Content-first mode works without KB too |
Conclusion: FCD is a specialized entry point, not a separate product. The enrichment pipeline is the differentiator — but it's currently locked to one template instead of being available to all 17.
Recommendation: Merge Into Unified GTM Studio¶
Single entry point: /dashboard/user/ai-presentation¶
GTM Studio
├── Research Mode ← absorbs FCD wizard
│ "I have a target company. Research them, then help me prepare."
│ Input: company name/URL + what you're selling + call objective
│ Output: enrichment dossier + template of your choice (not just 8-slide deck)
│
├── Create Mode ← current template picker
│ "I know what I need. Generate it."
│ Input: template selection + your content
│ Output: presentation / brief / listing content
│
├── Test Mode ← current A/B testing
│ "I have content. Help me optimize it."
│
└── Practice Mode ← current dry-runs
"I have a deck. Simulate the buyer conversation."
What changes:¶
- Enrichment becomes a pre-step available to ANY template — not just FCD's 8-slide deck
- FCD route redirects to GTM Studio Research Mode
- "First Call Deck" remains as a template name (it's a valid content type, like "Co-Sell Brief")
- Single nav item instead of two
What stays:¶
- All existing schemas (GtmContentSchema, FirstCallEnrichmentSchema) — unchanged
- All existing services — unchanged
- Portability grades — unchanged (both already A/A)
- MCP tool surface — simplified (one namespace)
The "easy to spread" pitch:¶
"GTM Studio: Research any company, generate your pitch, practice with AI buyers, then A/B test what works."
One sentence. Four modes. No confusion about which menu item to click.
Portability Audit Alignment¶
Per PARTNER_OUTPUT_PORTABILITY_AUDIT.md:
| Audit Item | Current Grade | Impact of Merge |
|---|---|---|
| #1 GTM Content Schema | A/A | Unchanged — still the output schema |
| #4 First Call Enrichment | A/A | Expanded — enrichment available to all templates |
| #7 A/B Testing Results | A/A | Unchanged |
| #8 MCP Tool Outputs | A+/A+ | Simplified — one tool namespace instead of two entry points |
The merge strengthens the portability story by making enrichment a composable capability rather than a siloed feature.
New Ideas — Implementation Specs¶
Idea 1: Partner Sales Readiness (A/B + Dry-Run Scoring)¶
Current state: A/B testing exists for marketplace listing content. Dry-runs exist for simulating buyer Q&A.
Proposed: Combine them — generate two versions of a pitch, run both through dry-run AI personas, score each version on how well it handles buyer objections.
Gamification angle: Score sellers on their ability to respond to AI buyer personas. Leaderboard. Certification-style badges. This opens a new product wedge:
"Partner Sales Readiness" — when partners onboard new employees, those employees practice against AI buyers tuned to specific industries before they ever get on a real call.
Novel? Yes. Sales enablement tools exist (Gong, Chorus) but they analyze AFTER real calls. This is pre-call simulation with scoring — practice mode, not post-mortem. The gamification + scoring makes it measurable and spreadable.
Market signal: Partners are increasingly hiring based on demonstrated ability (public GitHub repos for engineers). For alliance managers and pre-sales people, a scored dry-run portfolio could serve the same function — proof of preparation ability rather than resume fluff.
1.1 Scoring Rubric Schema¶
// app/Extensions/AiPresentation/System/Schema/ReadinessScoreSchema.php
class ReadinessScoreSchema
{
public string $version = '1.0';
// Per-question scoring (generated by Claude after each dry-run response)
public array $question_scores = [
[
'question_id' => 'string', // UUID
'persona' => 'string', // e.g. 'budget_holder'
'industry' => 'string', // e.g. 'financial_services'
'question_text' => 'string',
'user_response' => 'string', // what the seller typed/said
'scores' => [
'relevance' => 'int (1-5)', // did the answer address the question?
'specificity' => 'int (1-5)', // concrete details vs hand-waving
'objection_handling' => 'int (1-5)', // addressed underlying concern?
'cultural_fluency' => 'int (1-5)', // used appropriate terminology? (ties to Idea 2)
'confidence' => 'int (1-5)', // tone: assertive without overselling
],
'feedback' => 'string', // Claude-generated coaching note
'improvement_hint' => 'string', // one specific thing to try differently
]
];
// Aggregate session score
public array $session_summary = [
'overall_score' => 'int (0-100)', // weighted composite
'persona_breakdown' => 'array', // score per persona tested
'strongest_area' => 'string', // e.g. 'objection_handling'
'weakest_area' => 'string', // e.g. 'specificity'
'improvement_vs_last' => 'float|null', // % change from previous attempt
'readiness_tier' => 'string', // novice | prepared | proficient | expert
];
// Weights (configurable per org)
public array $weights = [
'relevance' => 0.25,
'specificity' => 0.20,
'objection_handling' => 0.25,
'cultural_fluency' => 0.15,
'confidence' => 0.15,
];
}
1.2 Database Schema¶
-- Readiness sessions (one per practice attempt)
CREATE TABLE readiness_sessions (
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT UNSIGNED NOT NULL,
company_id BIGINT UNSIGNED NULL, -- optional org context
presentation_id BIGINT UNSIGNED NULL, -- linked AiPresentation
variant_label VARCHAR(50) NULL, -- 'A' or 'B' for A/B scoring
persona_ids JSON NOT NULL, -- which personas were used
industry VARCHAR(100) NULL,
company_type VARCHAR(50) NULL,
revenue_tier VARCHAR(50) NULL,
culture_pack_id BIGINT UNSIGNED NULL, -- ties to Idea 2
overall_score TINYINT UNSIGNED NULL, -- 0-100
readiness_tier VARCHAR(20) NULL,
score_breakdown JSON NULL, -- full ReadinessScoreSchema
started_at TIMESTAMP NOT NULL,
completed_at TIMESTAMP NULL,
created_at TIMESTAMP,
updated_at TIMESTAMP,
INDEX idx_user_score (user_id, overall_score),
INDEX idx_user_date (user_id, completed_at),
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
-- Per-question scores (for drill-down analytics)
CREATE TABLE readiness_question_scores (
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
session_id BIGINT UNSIGNED NOT NULL,
question_id CHAR(36) NOT NULL, -- UUID
persona VARCHAR(50) NOT NULL,
question_text TEXT NOT NULL,
user_response TEXT NULL,
relevance TINYINT UNSIGNED NOT NULL,
specificity TINYINT UNSIGNED NOT NULL,
objection_handling TINYINT UNSIGNED NOT NULL,
cultural_fluency TINYINT UNSIGNED NOT NULL,
confidence TINYINT UNSIGNED NOT NULL,
composite_score TINYINT UNSIGNED NOT NULL, -- weighted single score
feedback TEXT NULL,
improvement_hint TEXT NULL,
created_at TIMESTAMP,
FOREIGN KEY (session_id) REFERENCES readiness_sessions(id) ON DELETE CASCADE
);
-- Badges / certifications
CREATE TABLE readiness_badges (
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT UNSIGNED NOT NULL,
badge_type VARCHAR(50) NOT NULL, -- 'first_session', 'proficient_financial', etc.
badge_label VARCHAR(100) NOT NULL,
earned_at TIMESTAMP NOT NULL,
session_id BIGINT UNSIGNED NULL,
metadata JSON NULL, -- criteria snapshot
created_at TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
-- Leaderboard view (materialized or computed)
-- Aggregates: user_id, avg_score, total_sessions, best_tier, badges_count
1.3 Service Architecture¶
app/Extensions/AiPresentation/System/Services/
├── ReadinessService.php ← orchestrator
│ ├── startSession() - create session, select personas
│ ├── scoreResponse() - score a single Q&A via Claude
│ ├── completeSession() - aggregate scores, assign tier
│ ├── compareVariants() - A/B: which variant scored better?
│ └── getImprovementTrack() - score history over time
│
├── ReadinessScoringEngine.php ← scoring logic
│ ├── scoreQuestion() - per-question rubric evaluation
│ ├── aggregateSession() - weighted composite
│ ├── determineTier() - novice/prepared/proficient/expert
│ └── generateFeedback() - coaching notes via Claude
│
├── ReadinessBadgeService.php ← gamification
│ ├── evaluateBadges() - check if session triggers any badges
│ ├── getBadgeDefinitions() - static badge catalog
│ └── getUserBadges() - earned badges for user
│
└── ReadinessReportService.php ← export
├── generateReport() - PDF/JSON readiness report
├── getLeaderboard() - org-wide rankings
└── exportPortfolio() - shareable "readiness portfolio"
Scoring prompt strategy: After each user response in dry-run mode, send a scoring prompt to Claude:
You are evaluating a sales professional's response to a simulated buyer question.
Buyer Persona: {persona_name} — {persona_description}
Industry: {industry} with context: {industry_overlay}
Company Culture: {culture_pack if available}
Question asked: "{question_text}"
Seller's response: "{user_response}"
Score each dimension 1-5:
- relevance: Did the answer directly address the question?
- specificity: Were concrete details, numbers, or examples provided?
- objection_handling: Was the underlying concern acknowledged and addressed?
- cultural_fluency: Did the response use appropriate terminology for this buyer's context?
- confidence: Was the tone appropriately assertive without overselling?
Return JSON with scores, a 1-sentence feedback note, and a 1-sentence improvement hint.
1.4 A/B Variant Comparison Flow¶
User generates Pitch A and Pitch B (via Create Mode or manually)
│
▼
Practice Mode: run dry-run for Pitch A against 3 personas
│ scores: [82, 74, 88] → avg 81.3
▼
Practice Mode: run dry-run for Pitch B against same 3 personas
│ scores: [90, 85, 79] → avg 84.7
▼
Comparison report:
- Pitch B scores 4.2% higher overall
- Pitch B stronger on objection_handling (+12%)
- Pitch A stronger on specificity (+6%)
- Recommendation: Use Pitch B, but incorporate Pitch A's
specific data points for the Technical Lead persona
1.5 Badge Catalog (v1)¶
| Badge | Criteria | Icon |
|---|---|---|
| First Steps | Complete first practice session | tabler-rocket |
| Consistent Performer | Score 70+ on 5 consecutive sessions | tabler-chart-line |
| Objection Slayer | Score 5/5 on objection_handling for 3+ questions in one session | tabler-shield-check |
| Industry Expert: | Score 85+ in a specific industry 3 times | tabler-building-bank |
| Culture Chameleon | Score 4+ on cultural_fluency across 3 different culture packs | tabler-language |
| Proficient Seller | Reach "proficient" tier | tabler-certificate |
| Expert Seller | Reach "expert" tier | tabler-trophy |
| A/B Champion | Run 5 A/B variant comparisons | tabler-ab-2 |
| Speed Learner | Improve score by 20+ points within 3 sessions | tabler-trending-up |
Idea 2: Company Culture as a Persona Trait¶
Current state: DryRunService supports 5 buyer personas, 9 industries, 9 AI business types, 4 company types, 6 revenue tiers. IndustryPersonaContext adds industry-specific behavioral overlays (decision_culture, hidden_concerns, procurement_dynamics, etc.).
Proposed: Add company-specific cultural vocabulary as a persona modifier. Not generic industry traits — actual company-specific communication patterns.
Examples from lived experience:
| Company | Cultural Vocabulary | Communication Pattern |
|---|---|---|
| AWS | LPs (Leadership Principles), WBRs (Weekly Business Reviews), MBRs (Monthly Business Reviews), EBCs (Executive Briefing Centers), mechanisms, tenets, 6-pagers, PR/FAQ | Data-driven, customer-obsessed framing, "working backwards" |
| Accenture | SOWs, "let there be change," capability leads, diamond-level, new applied now | Consulting-speak, transformation narrative, stakeholder alignment |
| Bank of America | responsible growth, eight lines of business, operational excellence | Risk-aware, compliance-first, measured language |
| Wells Fargo | team member (not employee), control environment, enterprise risk | Post-crisis careful, governance-heavy |
| Walmart | EDLP (everyday low prices), merchant mindset, Sam's rules | Cost-conscious, direct, scale-focused |
| Air Force | OPRs, EPRs, mission-first, wingman culture, OODA loop | Hierarchical, mission-outcome framing, brief/debrief cadence |
2.1 CompanyCultureContext Class¶
// app/Extensions/AiPresentation/System/Context/CompanyCultureContext.php
class CompanyCultureContext
{
/**
* Structure mirrors IndustryPersonaContext but is company-specific.
* Each pack is a self-contained profile that modifies persona behavior.
*/
public static function getCulturePack(string $companySlug): ?array
{
return self::CULTURE_PACKS[$companySlug] ?? null;
}
public static function getAllPacks(): array
{
return self::CULTURE_PACKS;
}
public static function getPacksByCategory(string $category): array
{
return array_filter(self::CULTURE_PACKS, fn($p) => $p['category'] === $category);
}
private const CULTURE_PACKS = [
'aws' => [
'company_name' => 'Amazon Web Services',
'category' => 'hyperscaler',
'vocabulary' => [
'LP' => 'Leadership Principle — one of 16 cultural tenets',
'WBR' => 'Weekly Business Review — operational metrics cadence',
'MBR' => 'Monthly Business Review — strategic review',
'EBC' => 'Executive Briefing Center — customer/partner presentations',
'6-pager' => 'Narrative document format (no slides for internal meetings)',
'PR/FAQ' => 'Press Release / FAQ format for new initiatives',
'mechanism' => 'A repeatable process with a forcing function',
'tenet' => 'A guiding principle for a team or initiative',
'bar raiser' => 'Senior evaluator in hiring process',
'working backwards' => 'Start from customer need, reason backward to solution',
],
'communication_norms' => [
'Data over anecdotes — every claim needs a metric',
'Customer obsession framing: start with the customer problem',
'Disagree and commit — voice concerns, then align',
'Bias for action — propose experiments, not studies',
'Meetings start with silent reading of a 6-pager (no pre-reads)',
],
'decision_pattern' => 'Data-driven, LP-referenced, customer-backwards',
'meeting_culture' => '6-pager silent reads, WBR cadence, action items with owners',
'red_flags' => [
'Using slides in internal meetings (perceived as hiding behind bullet points)',
'Saying "best practice" (AWS prefers "mechanisms" and context-specific solutions)',
'Vague ROI claims without supporting data',
],
'power_phrases' => [
'We built a mechanism for...',
'Working backwards from the customer...',
'The data shows...',
'Our tenet here is...',
],
],
'accenture' => [
'company_name' => 'Accenture',
'category' => 'consulting',
'vocabulary' => [
'SOW' => 'Statement of Work',
'capability lead' => 'Senior leader owning a service line',
'diamond' => 'Top client tier (Diamond/Platinum/Gold)',
'new applied now' => 'Brand tagline — technology + human ingenuity',
'managed service' => 'Outsourced operations capability',
],
'communication_norms' => [
'Transformation narrative — everything is a journey',
'Stakeholder alignment language — "bringing everyone along"',
'Polished, structured communication — executive summaries first',
'Framework-heavy — 2x2 matrices, maturity models',
'Always connect to business outcomes, never just technology',
],
'decision_pattern' => 'Consensus-driven, framework-validated, sponsor-dependent',
'meeting_culture' => 'Deck-driven, executive summary up front, action-oriented',
'red_flags' => [
'Overly technical without business impact framing',
'Skipping the "so what" — always connect to value',
'Not knowing their client tier system (Diamond matters)',
],
'power_phrases' => [
'This accelerates your transformation journey...',
'Our capability in this space...',
'Aligned to your strategic priorities...',
],
],
// Additional v1 packs: 'bofa', 'wells_fargo', 'walmart', 'us_air_force',
// 'jpmorgan', 'deloitte', 'microsoft', 'google_cloud', 'salesforce',
// 'us_army', 'us_navy', 'dod_civilian', 'oracle', 'sap',
// 'ibm', 'cigna', 'unitedhealth', 'kaiser', 'anthem'
];
/**
* Format culture pack for injection into DryRunService prompt.
*/
public static function formatForPrompt(string $companySlug): string
{
$pack = self::getCulturePack($companySlug);
if (!$pack) return '';
$sections = [];
$sections[] = "COMPANY CULTURE CONTEXT: {$pack['company_name']}";
$sections[] = "\nKey Vocabulary (use these terms naturally):";
foreach ($pack['vocabulary'] as $term => $def) {
$sections[] = " - {$term}: {$def}";
}
$sections[] = "\nCommunication Norms:";
foreach ($pack['communication_norms'] as $norm) {
$sections[] = " - {$norm}";
}
$sections[] = "\nDecision Pattern: {$pack['decision_pattern']}";
$sections[] = "Meeting Culture: {$pack['meeting_culture']}";
$sections[] = "\nRed Flags (things that lose credibility with this buyer):";
foreach ($pack['red_flags'] as $flag) {
$sections[] = " - {$flag}";
}
$sections[] = "\nPower Phrases (language that resonates):";
foreach ($pack['power_phrases'] as $phrase) {
$sections[] = " - \"{$phrase}\"";
}
return implode("\n", $sections);
}
}
2.2 Database Schema for Custom Culture Packs¶
-- User-contributed / admin-curated culture packs
CREATE TABLE company_culture_packs (
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
slug VARCHAR(50) UNIQUE NOT NULL,
company_name VARCHAR(200) NOT NULL,
category VARCHAR(50) NOT NULL, -- hyperscaler, consulting, banking, etc.
source ENUM('curated', 'user', 'enrichment') DEFAULT 'curated',
created_by BIGINT UNSIGNED NULL,
vocabulary JSON NOT NULL,
communication_norms JSON NOT NULL,
decision_pattern VARCHAR(500) NULL,
meeting_culture VARCHAR(500) NULL,
red_flags JSON NULL,
power_phrases JSON NULL,
is_public BOOLEAN DEFAULT FALSE, -- visible to all users?
usage_count INT UNSIGNED DEFAULT 0,
created_at TIMESTAMP,
updated_at TIMESTAMP,
INDEX idx_category (category),
INDEX idx_public (is_public)
);
-- User overlays (personal notes on top of curated packs)
CREATE TABLE company_culture_overlays (
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT UNSIGNED NOT NULL,
culture_pack_id BIGINT UNSIGNED NOT NULL,
custom_vocabulary JSON NULL, -- additional terms
custom_notes TEXT NULL, -- free-form personal notes
custom_red_flags JSON NULL,
custom_power_phrases JSON NULL,
created_at TIMESTAMP,
updated_at TIMESTAMP,
UNIQUE KEY idx_user_pack (user_id, culture_pack_id),
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (culture_pack_id) REFERENCES company_culture_packs(id) ON DELETE CASCADE
);
2.3 Integration with DryRunService¶
The existing DryRunService::generateQuestions() method builds a prompt with persona, industry, and company type context. Culture packs slot in as an additional prompt section:
// In DryRunService::generateQuestions(), after existing context building:
// Existing
$industryContext = IndustryPersonaContext::getContext($industry);
// New — add culture pack if selected
$cultureContext = '';
if ($culturePack = $request->input('culture_pack')) {
$cultureContext = CompanyCultureContext::formatForPrompt($culturePack);
}
// Inject into prompt after industry context:
$prompt = "...
{$industryContext}
{$cultureContext}
Generate questions this buyer persona would ask...
";
No breaking changes — culture_pack is an optional parameter. Existing dry-runs work exactly as before.
2.4 Data Source Strategy (Phased)¶
| Phase | Source | Scope | Effort |
|---|---|---|---|
| v1 | Curated packs (hardcoded) | 20 companies (hyperscalers, banks, consulting, defense) | Low — PHP constants |
| v2 | DB-backed + admin UI | Admins create/edit packs, users browse | Medium — CRUD + UI |
| v3 | User overlays | Users add personal notes to curated packs | Medium — overlay merge logic |
| v4 | Enrichment-derived | Auto-generate culture signals from 10-K, Glassdoor, LinkedIn | High — NLP pipeline |
Idea 3: The "Research + Sell" Flow Question¶
The user asked: "If I'm researching a company, where do I input what I'm trying to sell them?"
This is the core UX question the merge solves. In the unified model:
Research Mode Input Form:
┌─────────────────────────────────────────┐
│ Target Company: [_________________________] │
│ Company URL: [_________________________] │
│ │
│ What are you selling? │
│ ┌─────────────────────────────────────────┐ │
│ │ [Product/service description or select │ │
│ │ from your brand voice profiles] │ │
│ └─────────────────────────────────────────┘ │
│ │
│ Call Objective: │
│ ○ Discovery ○ Value Prop ○ Qualify │
│ │
│ Relationship: │
│ ○ Partner Co-Sell ○ Buyer ○ New to MP │
│ │
│ Output Template: │
│ [First Call Deck ▼] (or Co-Sell Brief, │
│ Value Prop, etc.) │
│ │
│ [Research & Generate] │
└─────────────────────────────────────────────┘
This single form answers: who am I targeting, what am I selling, why am I calling, what's our relationship, and what format do I need? Currently this is split across two separate features.
Idea 4: Partner-Buyer Matching vs Partner Co-Sell Matching¶
Clarification: These are two distinct motions that both live under "Research Mode":
| Motion | Who's Researching | Who's the Target | Output |
|---|---|---|---|
| Partner Co-Sell | ISV partner | Another ISV partner | Joint GTM deck, co-sell brief |
| Partner-Buyer | ISV partner | End customer (enterprise) | Value prop deck, qualification brief |
The FCD wizard already handles both via its three scenarios. The merge preserves this — the "Relationship" selector in Research Mode maps directly to persona_mode in FirstCallEnrichmentSchema.
Implementation Plan: Merge FCD into GTM Studio¶
Decision¶
Merge FCD into GTM Studio as Research Mode (recommended — see analysis above).
Implementation is low-risk: the backend is already shared. The work is primarily UI reorganization and route consolidation.
Phase 1: Research Mode Tab (Core Merge)¶
Goal: Add "Research" as a mode/tab in the AI Presentation UI, absorbing the FCD wizard flow.
1.1 Files to Create¶
| File | Purpose |
|---|---|
app/Extensions/AiPresentation/resources/views/modes/research.blade.php |
Research Mode tab content — reimplements FCD wizard steps inline |
app/Livewire/Dashboard/ResearchModeWizard.php |
New Livewire component (replaces FirstCallDeckWizard in context of GTM Studio) |
1.2 Files to Modify¶
| File | Change |
|---|---|
app/Extensions/AiPresentation/resources/views/index-v2.blade.php |
Add 4-mode tab bar: Research / Create / Test / Practice |
app/Extensions/AiPresentation/System/AiPresentationServiceProvider.php |
Add research-mode routes under /ai-presentation/research/* |
app/Extensions/AiPresentation/System/Http/Controllers/AiPresentationController.php |
Add researchMode(), runResearchEnrichment(), generateFromResearch() methods |
app/Extensions/AiPresentation/System/Services/FirstCallEnrichmentService.php |
No changes needed — already template-agnostic internally |
app/Extensions/AiPresentation/System/Services/TemplateManagerService.php |
Add getEnrichmentCompatibleTemplates() — returns templates that benefit from research context |
1.3 Tab Bar Implementation¶
{{-- index-v2.blade.php — new tab bar above existing content --}}
<div class="flex border-b border-gray-200 dark:border-gray-700 mb-6" role="tablist">
<button
@click="activeMode = 'research'"
:class="activeMode === 'research'
? 'border-[#330582] text-[#330582] dark:text-[#9a34cd] dark:border-[#9a34cd]'
: 'border-transparent text-gray-500'"
class="px-6 py-3 border-b-2 font-medium text-sm transition-colors"
role="tab"
>
<i class="ki-outline ki-magnifier mr-2"></i>Research
</button>
<button
@click="activeMode = 'create'"
:class="activeMode === 'create' ? '...' : '...'"
class="px-6 py-3 border-b-2 font-medium text-sm transition-colors"
role="tab"
>
<i class="ki-outline ki-document mr-2"></i>Create
</button>
<button
@click="activeMode = 'test'"
:class="activeMode === 'test' ? '...' : '...'"
class="px-6 py-3 border-b-2 font-medium text-sm transition-colors"
role="tab"
>
<i class="ki-outline ki-chart mr-2"></i>Test
</button>
<button
@click="activeMode = 'practice'"
:class="activeMode === 'practice' ? '...' : '...'"
class="px-6 py-3 border-b-2 font-medium text-sm transition-colors"
role="tab"
>
<i class="ki-outline ki-people mr-2"></i>Practice
</button>
</div>
1.4 Research Mode — Wizard Steps (Reimplemented)¶
The existing FirstCallDeckWizard.php has 4 steps. Research Mode reimplements the same flow but adds template selection:
Step 1: Relationship & Objective
- Persona mode: partner_cosell | buyer_prospect | new_to_marketplace
- Call objective: discovery | pitch | qualify | onboard
- Your role: alliance_manager | sales | marketing | sa | executive
Step 2: Target Company Details
- Company name (required)
- Company URL (optional)
- Marketplace listing URL (optional, for partner_cosell)
- What you're selling (textarea — or pull from brand voice)
- Target industry (dropdown)
Step 3: Research & Enrichment
- [Run Research] → FirstCallEnrichmentService::enrichToSchema()
- Display enrichment dossier (company overview, market intel, news signals)
- User can edit/annotate enrichment before proceeding
Step 4: Generate Content ← THIS IS THE NEW PART
- Template picker: choose ANY template (not just First Call Deck)
- Templates flagged as "enrichment-compatible" are highlighted
- Enrichment data passed as enrichment_data field to TemplateManagerService
- [Generate] → same pipeline as Create Mode, but with research context injected
Key difference from current FCD: Step 4 no longer locks you into the 8-slide First Call Deck. You can take research on "Acme Corp" and generate a Co-Sell Brief, a Value Proposition deck, or a First Call Deck — your choice.
1.5 Enrichment Injection into Templates¶
Currently only FirstCallDeckTemplate knows how to use enrichment data. To make enrichment available to all templates:
// In PresentationTemplate.php (abstract base), add:
protected function buildEnrichmentContext(?array $enrichmentData): string
{
if (!$enrichmentData) return '';
return "
RESEARCH CONTEXT (from automated internet enrichment):
Company: {$enrichmentData['company_name']}
Industry: {$enrichmentData['industry'] ?? 'Not identified'}
Company Overview:
{$enrichmentData['synthesized_brief'] ?? 'No overview available'}
Key Signals:
" . collect($enrichmentData['news_signals'] ?? [])->map(fn($s) => "- {$s}")->implode("\n") . "
Market Intelligence:
" . ($enrichmentData['market_intel'] ?? 'No market data available') . "
Use this research to make the content specific and relevant to this company.
Do NOT fabricate details not present in the research.
";
}
Each template's buildPrompt() method already accepts a $context array. Enrichment data flows through as $context['enrichment_data'] — templates that want to use it call $this->buildEnrichmentContext($context['enrichment_data']). Templates that don't care simply ignore it.
Phase 2: Route Redirect & Nav Consolidation¶
2.1 FCD Route Redirect¶
// In routes/panel.php or AiPresentationServiceProvider.php
// Old route → redirect to Research Mode
Route::get('dashboard/user/first-call-deck', function () {
return redirect()->route('dashboard.user.ai-presentation.index', ['mode' => 'research']);
})->name('panel.user.first-call-deck.index');
2.2 Nav Item Consolidation¶
// Migration: consolidate_fcd_nav_item.php
public function up(): void
{
// Remove the separate "First Call Deck" menu item
DB::table('menu_items')
->where('route_name', 'dashboard.user.first-call-deck')
->delete();
// Update AI Presentation label to "GTM Studio"
DB::table('menu_items')
->where('route_name', 'dashboard.user.ai-presentation')
->update([
'title' => 'GTM Studio',
'icon' => 'tabler-rocket', // or keep existing
]);
}
public function down(): void
{
// Re-add FCD menu item if rolling back
// ... inverse of up()
}
2.3 Breadcrumb & Page Title Updates¶
| Location | Before | After |
|---|---|---|
| Page title | "AI Presentation" | "GTM Studio" |
| Breadcrumb | Dashboard > AI Presentation | Dashboard > GTM Studio |
| Hero card title | "GTM Content Studio" | "GTM Studio" |
| Hero card subtitle | (current) | "Research any company, generate your pitch, practice with AI buyers, then A/B test what works." |
Phase 3: Practice Mode & Test Mode Tab Integration¶
These already exist as features — they just need to be surfaced as tabs rather than buried in the UI.
3.1 Practice Mode Tab¶
Currently: dry-run is accessed from within a generated presentation's detail view.
After merge: Practice Mode tab shows:
- Upload a deck (existing uploadDeck() flow)
- Or select from gallery (existing presentations)
- Configure persona/industry/company type
- Run dry-run (existing DryRunService)
- View history (existing dryRunHistory())
{{-- modes/practice.blade.php --}}
<div x-show="activeMode === 'practice'" x-cloak>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
{{-- Left: deck selection --}}
<div class="card">
<div class="card-header"><h3 class="card-title">Select Your Deck</h3></div>
<div class="card-body">
{{-- Gallery picker or upload --}}
@include('ai-presentation::partials.deck-selector')
</div>
</div>
{{-- Right: persona config --}}
<div class="card">
<div class="card-header"><h3 class="card-title">Configure Buyer Persona</h3></div>
<div class="card-body">
{{-- Persona, industry, company type, revenue tier dropdowns --}}
{{-- Culture pack selector (Idea 2, when ready) --}}
@include('ai-presentation::partials.dry-run-config')
</div>
</div>
</div>
{{-- Results area --}}
<div class="card mt-6" x-show="dryRunResults">
@include('ai-presentation::partials.dry-run-results')
</div>
</div>
3.2 Test Mode Tab¶
Currently: A/B testing lives at /ai-presentation/ab-testing/* with its own views.
After merge: Test Mode tab surfaces the A/B dashboard inline: - Active tests summary - Create new test (links to existing create flow) - Test results with statistical significance
No major refactor needed — can start by embedding the existing A/B dashboard view, then iterate.
Phase 4: Cleanup & Deprecation¶
| Task | Details | Risk |
|---|---|---|
Deprecate FirstCallDeckWizard.php |
Mark as @deprecated, keep for 2 releases, then remove |
Low — redirect handles traffic |
| Deprecate FCD blade view | first-call-deck/index.blade.php — show deprecation notice + redirect link |
Low |
| Update MCP tools | Consolidate any FCD-specific MCP endpoints into GTM Studio namespace | Low — schema unchanged |
| Update docs/help text | Any user-facing references to "First Call Deck" as a separate product → "GTM Studio Research Mode" | Low |
| Analytics migration | Ensure FCD usage metrics map to Research Mode in analytics | Medium — verify event names |
Implementation Sequence¶
Phase 1 (Core Merge) ~3-4 days
├── 1a. Tab bar + mode switching (Alpine) ½ day
├── 1b. ResearchModeWizard Livewire component 1 day
├── 1c. Research Mode blade views 1 day
├── 1d. Enrichment injection into base template ½ day
└── 1e. Template compatibility flagging ½ day
Phase 2 (Routes & Nav) ~1 day
├── 2a. FCD route redirect ¼ day
├── 2b. Nav migration ¼ day
└── 2c. Title/breadcrumb updates ½ day
Phase 3 (Tab Integration) ~2 days
├── 3a. Practice Mode tab 1 day
└── 3b. Test Mode tab 1 day
Phase 4 (Cleanup) ~1 day
├── 4a. Deprecation notices ¼ day
├── 4b. MCP consolidation ¼ day
└── 4c. Docs & analytics ½ day
Total: ~7-8 days of focused work
Risk Assessment¶
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Users bookmarked FCD URL | High | Low | 301 redirect preserves access |
| Enrichment adds latency to non-FCD templates | Medium | Low | Enrichment is opt-in, not default |
| Tab UI feels cluttered with 4 modes | Low | Medium | Progressive disclosure — show Research + Create by default, Test + Practice as advanced |
| MCP consumers break | Low | Low | Old endpoints redirect, schemas unchanged |
Success Metrics¶
| Metric | Before Merge | Target (30 days post) |
|---|---|---|
| Users confused about FCD vs AI Presentation | Unmeasured (anecdotal) | 0 support tickets |
| Enrichment usage across templates | 1 template (FCD only) | 3+ templates using enrichment |
| GTM Studio daily active users | FCD + AI Pres combined | Same or higher (no drop-off) |
| Time to first content generation | ~4 min (FCD wizard) | ~3 min (streamlined Research Mode) |
| Dry-run sessions per user per week | Current baseline | +20% (surfaced as tab, not buried) |
Terminology Reference¶
| Term | Definition (for this document) |
|---|---|
| FCD | First Call Deck — a presentation for a first conversation with a prospect or partner |
| GTM Studio | The AI Presentation feature (/ai-presentation) — full content generation platform |
| Enrichment | Automated internet research (Serper + marketplace scraping + Claude synthesis) |
| Dry-run | AI buyer persona simulation — practice Q&A before a real call |
| A/B Testing | Variant testing for marketplace listing content with statistical significance |
| EBC | Executive Briefing Center — AWS program where partners present to enterprise decision-makers |
| LP | Leadership Principle — AWS's 16 cultural tenets that drive decision-making |
| WBR/MBR | Weekly/Monthly Business Review — AWS operational cadence meetings |
This document captures the product clarity analysis. Implementation changes (if approved) should be tracked separately.