Product Management
What I Do
I lead product strategy and execution by defining vision, prioritizing features, and coordinating cross-functional teams. I balance user needs, business objectives, and technical constraints to deliver products that achieve market success.
When to Use Me
- Defining product vision and strategy
- Prioritizing features and roadmap planning
- Conducting market and user research
- Setting and tracking product KPIs
- Aligning stakeholders on product direction
- Managing the product lifecycle from inception to retirement
Core Concepts
- Product Vision: Long-term purpose and direction
- User Personas: Target user archetypes
- Jobs to be Done: Tasks users hire products to accomplish
- Prioritization Frameworks: RICE, MoSCoW, Kano, Value vs Effort
- OKRs: Objectives and Key Results for goal setting
- Product-Market Fit: Validating product-market alignment
- Lean Product Development: Build-Measure-Learn cycles
- A/B Testing: Data-driven feature validation
- Roadmapping: Communicating strategy and progress
- North Star Metric: Primary growth metric alignment
Code Examples
Product Strategy Builder
class ProductStrategy {
constructor() {
this.vision = null;
this.objectives = [];
this.targetUsers = [];
this.competitors = [];
this.differentators = [];
}
setVision(vision) {
this.vision = {
statement: vision,
timeframe: '3-5 years',
validated: false,
stakeholderSignoff: []
};
return this;
}
addObjective(objective) {
const objectiveNode = {
id: this.generateId(),
title: objective.title,
keyResults: objective.keyResults?.map(kr => ({
id: this.generateId(),
description: kr,
target: kr.target,
current: kr.current || 0,
unit: kr.unit || 'percent',
progress: 0
})),
status: 'draft',
owner: objective.owner,
initiatives: []
};
this.objectives.push(objectiveNode);
return this;
}
defineTargetUsers(personas) {
this.targetUsers = personas.map(p => ({
id: this.generateId(),
name: p.name,
role: p.role,
goals: p.goals,
painPoints: p.painPoints,
behaviors: p.behaviors,
jobsToBeDone: p.jobsToBeDone?.map(j => ({
task: j.task,
importance: j.importance,
currentSolutions: j.currentSolutions,
gaps: j.gaps
})),
marketSize: p.marketSize || null
}));
return this;
}
analyzeCompetitors() {
return this.competitors.map(competitor => ({
...competitor,
strengths: competitor.strengths || [],
weaknesses: competitor.weaknesses || [],
marketShare: competitor.marketShare || 0,
positioning: competitor.positioning,
threats: this.identifyThreats(competitor),
opportunities: this.identifyOpportunities(competitor)
}));
}
identifyThreats(competitor) {
return this.targetUsers
.filter(user =>
competitor.strengths.some(s =>
user.painPoints.some(p => p.includes(s))
)
)
.map(user => `Competitor ${competitor.name} addresses ${user.name}'s pain points`);
}
identifyOpportunities(competitor) {
return this.targetUsers
.filter(user =>
competitor.weaknesses.some(w =>
user.goals.some(g => g.includes(w))
)
)
.map(user => `Gap in ${competitor.name} for ${user.name}'s ${user.goals[0]}`);
}
generateStrategyCanvas() {
return {
vision: this.vision,
objectives: this.objectives,
targetUsers: this.targetUsers,
competitiveLandscape: this.analyzeCompetitors(),
differentiators: this.differentiators,
valueProposition: this.generateValueProposition()
};
}
generateValueProposition() {
return this.targetUsers.map(user => ({
user: user.name,
job: user.jobsToBeDone?.[0]?.task || 'Primary goal',
pains: user.painPoints.slice(0, 3),
gains: user.goals.slice(0, 3),
ourDifferentiators: this.differentiators.filter(d =>
user.painPoints.some(p =>
d.addresses?.some(a => p.includes(a))
)
)
}));
}
}
Feature Prioritizer
class FeaturePrioritizer {
constructor() {
this.features = [];
this.criteria = [];
}
addFeature(feature) {
const scoredFeature = {
...feature,
scores: {},
weightedScore: 0,
rank: null
};
this.features.push(scoredFeature);
return this;
}
setCriteria(criteria) {
this.criteria = criteria.map(c => ({
name: c.name,
weight: c.weight || 1,
scale: c.scale || { min: 1, max: 10 },
evaluate: c.evaluate
}));
return this;
}
prioritize(method = 'rice') {
switch (method) {
case 'rice':
return this.calculateRICE();
case 'moscow':
return this.categorizeMoSCoW();
case 'kano':
return this.categorizeKano();
case 'weighted':
return this.calculateWeightedScores();
default:
return this.calculateRICE();
}
}
calculateRICE() {
return this.features.map(feature => {
const reach = this.score(feature, 'reach');
const impact = this.score(feature, 'impact');
const confidence = this.score(feature, 'confidence');
const effort = this.score(feature, 'effort');
return {
...feature,
rice: {
reach,
impact,
confidence,
effort,
score: (reach * impact * confidence) / effort
}
};
}).sort((a, b) => b.rice.score - a.rice.score);
}
score(feature, criterion) {
const scores = {
reach: { low: 1, medium: 5, high: 10 },
impact: { minimal: 0.25, small: 0.5, medium: 1, large: 2, massive: 3 },
confidence: { low: 0.5, medium: 0.75, high: 1 },
effort: { months: 20, weeks: 10, days: 5 }
};
return scores[criterion]?.[feature[criterion]] || feature[criterion] || 5;
}
categorizeMoSCoW() {
const categories = {
mustHave: [],
shouldHave: [],
couldHave: [],
wontHave: []
};
const sorted = [...this.features].sort((a, b) =>
(b.value || 0) - (a.value || 0)
);
const totalValue = sorted.reduce((sum, f) => sum + (f.value || 0), 0);
const mustHaveThreshold = totalValue * 0.6;
const shouldHaveThreshold = totalValue * 0.85;
let cumulative = 0;
sorted.forEach(feature => {
cumulative += feature.value || 0;
if (cumulative <= mustHaveThreshold) {
categories.mustHave.push({ ...feature, rationale: 'Essential value' });
} else if (cumulative <= shouldHaveThreshold) {
categories.shouldHave.push({ ...feature, rationale: 'High value add' });
} else if (feature.importance <= 3) {
categories.couldHave.push({ ...feature, rationale: 'Nice to have' });
} else {
categories.wontHave.push({ ...feature, rationale: 'Out of scope' });
}
});
return categories;
}
categorizeKano() {
return this.features.map(feature => {
const assessment = {
attractive: this.assessAttractive(feature),
oneDimensional: this.assessOneDimensional(feature),
mustBe: this.assessMustBe(feature),
indifferent: this.assessIndifferent(feature),
reverse: this.assessReverse(feature)
};
const category = Object.entries(assessment)
.sort((a, b) => b[1] - a[1])[0][0];
return {
...feature,
kanoCategory: category,
satisfactionPotential: this.calculateSatisfactionPotential(assessment),
investmentPriority: this.mapToPriority(category)
};
});
}
calculateSatisfactionPotential(assessment) {
return (
(assessment.attractive * 1.5) +
assessment.oneDimensional -
(assessment.mustBe * 0.5)
);
}
mapToPriority(category) {
const priorities = {
mustBe: 1,
oneDimensional: 2,
attractive: 3,
indifferent: 4,
reverse: 5
};
return priorities[category];
}
}
Roadmap Generator
class RoadmapGenerator {
constructor() {
this.initiatives = [];
this.quarters = [];
this.themes = [];
}
addInitiative(initiative) {
this.initiatives.push({
id: this.generateId(),
...initiative,
status: 'planned',
progress: 0,
dependencies: initiative.dependsOn || [],
risks: initiative.risks || [],
metrics: initiative.successMetrics || []
});
return this;
}
setQuarters(quarters) {
this.quarters = quarters.map(q => ({
id: q.id,
name: q.name,
start: q.startDate,
end: q.endDate,
objectives: q.objectives || [],
capacity: q.capacity || 100,
allocated: 0,
initiatives: []
}));
return this;
}
setThemes(themes) {
this.themes = themes.map(t => ({
id: t.id,
name: t.name,
color: t.color || '#3b82f6',
description: t.description,
strategicAlignment: t.alignment
}));
return this;
}
assignToQuarters() {
const sorted = [...this.initiatives].sort((a, b) =>
(b.priority || 0) - (a.priority || 0)
);
this.quarters.forEach(quarter => {
const remainingCapacity = quarter.capacity - quarter.allocated;
sorted
.filter(i => !i.assignedQuarter && i.effort <= remainingCapacity)
.forEach(initiative => {
initiative.assignedQuarter = quarter.id;
initiative.startDate = quarter.start;
initiative.endDate = quarter.end;
quarter.initiatives.push(initiative);
quarter.allocated += initiative.effort;
});
});
return {
quarters: this.quarters,
unassigned: this.initiatives.filter(i => !i.assignedQuarter),
capacityUtilization: this.quarters.map(q => ({
quarter: q.name,
allocated: q.allocated,
capacity: q.capacity,
utilization: q.allocated / q.capacity
}))
};
}
generateVisualRoadmap() {
const assignments = this.assignToQuarters();
const timeline = assignments.quarters.map(quarter => ({
quarter: quarter.name,
period: `${quarter.start} - ${quarter.end}`,
width: 3,
items: quarter.initiatives.map(init => ({
id: init.id,
name: init.name,
theme: this.getThemeColor(init.theme),
duration: this.calculateDuration(init),
dependencies: init.dependencies.length > 0 ? 'Yes' : 'None',
milestone: init.isMilestone,
confidence: init.confidence || 'medium'
}))
}));
return {
title: 'Product Roadmap',
timeframe: `${assignments.quarters[0]?.start} - ${assignments.quarters[assignments.quarters.length - 1]?.end}`,
timeline,
themes: this.themes,
legend: this.generateLegend(),
notes: {
confidence: 'Confidence levels based on discovery completeness',
dependencies: 'Items with dependencies must be sequenced accordingly',
tentative: 'Items marked tentative are subject to change'
}
};
}
getThemeColor(themeId) {
return this.themes.find(t => t.id === themeId)?.color || '#888';
}
calculateDuration(initiative) {
const start = new Date(initiative.startDate);
const end = new Date(initiative.endDate);
return Math.ceil((end - start) / (1000 * 60 * 60 * 24));
}
generateOKRDashboard() {
return {
objectives: this.objectives,
keyResults: this.keyResults,
progress: this.calculateOverallProgress(),
health: this.assessOKRHealth(),
recommendations: this.generateRecommendations()
};
}
calculateOverallProgress() {
if (!this.keyResults?.length) return 0;
const total = this.keyResults.reduce((sum, kr) => {
if (kr.target === 0) return sum;
return sum + Math.min(100, (kr.current / kr.target) * 100);
}, 0);
return Math.round(total / this.keyResults.length);
}
assessOKRHealth() {
const progress = this.calculateOverallProgress();
const trend = this.calculateProgressTrend();
if (progress >= 70 && trend >= 0) return 'healthy';
if (progress >= 40 && trend >= 0) return 'at-risk';
if (progress < 40) return 'off-track';
return 'regressing';
}
}
Best Practices
- Start with clear problem definition, not solutions
- Deeply understand user needs through research
- Prioritize based on value and strategic alignment
- Communicate vision and progress consistently
- Make data-driven decisions when possible
- Balance short-term wins with long-term strategy
- Build and maintain cross-functional relationships
- Iterate quickly and validate assumptions
- Set clear success metrics before launching
- Continuously gather and act on feedback