UNPKG

positioning-statement-generator

Version:

Nail your product positioning in 10 minutes using April Dunford's Obviously Awesome framework

245 lines (205 loc) 6.65 kB
/** * Positioning Statement Generator - Core Logic * Based on April Dunford's "Obviously Awesome" Framework */ const AIEnhancer = require('./ai-enhancer'); class PositioningEngine { constructor(apiKey = null) { this.positioning = { productName: '', competitiveAlternatives: [], uniqueAttributes: [], valueThemes: [], targetMarket: '', marketCategory: '', }; this.ai = new AIEnhancer(apiKey); this.aiSuggestions = { problem: null, improvedValues: [], critique: null, alternativePositioning: [], suggestedCategories: [], }; } /** * Set product name */ setProductName(name) { this.positioning.productName = name; } /** * Add competitive alternatives (what customers use if you don't exist) */ addCompetitiveAlternatives(alternatives) { this.positioning.competitiveAlternatives = alternatives; } /** * Add unique attributes (features you have that alternatives don't) */ addUniqueAttributes(attributes) { this.positioning.uniqueAttributes = attributes; } /** * Add value themes (value enabled by unique attributes) */ addValueThemes(themes) { this.positioning.valueThemes = themes; } /** * Set target market (who cares most about that value) */ setTargetMarket(market) { this.positioning.targetMarket = market; } /** * Set market category (category that makes value obvious) */ setMarketCategory(category) { this.positioning.marketCategory = category; } /** * Generate positioning statement */ generatePositioningStatement() { const { productName, competitiveAlternatives, uniqueAttributes, valueThemes, targetMarket, marketCategory } = this.positioning; return `${productName} is a ${marketCategory} that helps ${targetMarket} ${valueThemes[0]}. Unlike ${competitiveAlternatives.join(', ')}, we ${uniqueAttributes[0]}.`; } /** * Generate elevator pitch (30 second version) */ generateElevatorPitch30() { const { productName, targetMarket, valueThemes, marketCategory } = this.positioning; return `${productName} helps ${targetMarket} ${valueThemes[0]}. We're the only ${marketCategory} that ${this.positioning.uniqueAttributes[0]}.`; } /** * Generate elevator pitch (2 minute version) */ generateElevatorPitch2Min() { const { productName, competitiveAlternatives, uniqueAttributes, valueThemes, targetMarket, marketCategory } = this.positioning; // Use AI-inferred problem if available, otherwise use fallback const problem = this.aiSuggestions.problem || this.ai.fallbackInferProblem(competitiveAlternatives); return `You know how ${targetMarket} struggle with ${problem}? Most companies use ${competitiveAlternatives[0]}, but that approach has limitations. ${productName} is a ${marketCategory} that solves this differently. We ${uniqueAttributes.join(', and we ')}. This means ${valueThemes.join(', ')}. We're built specifically for ${targetMarket} who need ${valueThemes[0]}.`; } /** * Generate hero copy for website */ generateHeroCopy() { const { productName, valueThemes, targetMarket } = this.positioning; const headline = `${valueThemes[0]} for ${targetMarket}`; const subheadline = `${productName} helps you ${valueThemes.slice(0, 3).join(', ')}`; const cta = 'Get Started'; return { headline, subheadline, cta, }; } /** * Generate competitive positioning matrix */ generateCompetitiveMatrix() { const { productName, competitiveAlternatives, uniqueAttributes } = this.positioning; const matrix = { headers: ['Feature', productName, ...competitiveAlternatives.slice(0, 2)], rows: uniqueAttributes.map(attr => [ attr, '✓', '✗', '✗', ]), }; return matrix; } /** * Generate messaging hierarchy */ generateMessagingHierarchy() { const { valueThemes, uniqueAttributes } = this.positioning; return { topLevel: valueThemes[0], pillars: valueThemes.slice(0, 3), proofPoints: uniqueAttributes, }; } /** * Generate AI-enhanced insights */ async generateAIInsights() { if (!this.ai.isEnabled()) { return; } const { targetMarket, competitiveAlternatives, valueThemes, productName, uniqueAttributes, marketCategory } = this.positioning; try { // Infer problem this.aiSuggestions.problem = await this.ai.inferProblem(targetMarket, competitiveAlternatives); // Improve value propositions if (valueThemes.length > 0) { const improved = await this.ai.improveValueProp(valueThemes[0], targetMarket); this.aiSuggestions.improvedValues.push(improved); } // Critique positioning const statement = this.generatePositioningStatement(); this.aiSuggestions.critique = await this.ai.critiquePositioning(statement); // Generate alternatives if (valueThemes.length > 0) { this.aiSuggestions.alternativePositioning = await this.ai.generateAlternatives( productName, targetMarket, valueThemes[0], marketCategory ); } // Suggest categories (if category not set yet) if (uniqueAttributes.length > 0 && valueThemes.length > 0) { this.aiSuggestions.suggestedCategories = await this.ai.suggestCategory( productName, uniqueAttributes, valueThemes, targetMarket ); } } catch (error) { console.error('Error generating AI insights:', error.message); } } /** * Get AI suggestions */ getAISuggestions() { return this.aiSuggestions; } /** * Check if AI is enabled */ isAIEnabled() { return this.ai.isEnabled(); } /** * Infer problem from competitive alternatives */ async inferProblem() { const { targetMarket, competitiveAlternatives } = this.positioning; return await this.ai.inferProblem(targetMarket, competitiveAlternatives); } /** * Get complete positioning document */ getCompleteDocument() { return { productName: this.positioning.productName, positioningStatement: this.generatePositioningStatement(), elevatorPitch30: this.generateElevatorPitch30(), elevatorPitch2Min: this.generateElevatorPitch2Min(), heroCopy: this.generateHeroCopy(), competitiveMatrix: this.generateCompetitiveMatrix(), messagingHierarchy: this.generateMessagingHierarchy(), rawData: this.positioning, }; } } module.exports = PositioningEngine;