4-question interview that instantly generates all validation content for an indie hacker's product idea. Produces landing page copy, Indie Hackers post, Reddit r/SideProject post, email sequence, and Founding Plan pre-sale offer — all in one markdown file. Use when user says "launch-kit", "/launch-kit", "아이디어 검증", "랜딩페이지 만들어줘", "validate my idea", "검증 키트", "launch my idea".
Transform a raw product idea into a complete set of launch-ready validation content through a lean 4-question interview. The output is a single markdown file with 5 content sections, ready to copy-paste into Carrd, Kit, Indie Hackers, and Reddit.
Output sections:
Key design principles:
English:
Korean:
Use this skill when the user wants to:
Note: Supported output languages are Korean and English only. Triggers in other languages will default to English output.
Do NOT use this skill when:
planning-interview)market-research-by-desire)business-avengers)Detect language from the trigger message and initialize session state.
function detectLanguage(trigger_message):
korean_markers = ["아이디어", "랜딩페이지", "검증", "런치킷", "만들어줘", "해줘"]
for marker in korean_markers:
if marker in trigger_message:
return "ko"
return "en"
session = {
language: detectLanguage(trigger_message),
product_name: null,
product_slug: null,
answers: {
problem: null, // Q1: specific problem and real situation
solution: null, // Q2: one-sentence differentiation
target: null, // Q3: target user with role and tools
mvp_scope: null // Q4: 3 must-haves + v2 deferred items
},
completeness: {
problem: 0,
solution: 0,
target: 0,
mvp_scope: 0
},
notes_imported: false,
notes_partial: { // tracks which fields were extracted from notes but need targeted follow-up
problem: false, // set true when: extracted word_count <= 15, or score < 3
solution: false,
target: false,
mvp_scope: false
},
output_path: null,
generated_at: null
}
Before asking the first interview question, check if the trigger message already contains substantial product description.
function extractInlineNotes(trigger_message):
content = remove_trigger_keyword(trigger_message)
word_count = count_words(content)
if word_count > 50:
return content
return null
Case A: Trigger contains more than 50 words of description
Extract answers from the inline notes without asking the user whether they have notes.
if inline_notes = extractInlineNotes(trigger_message):
session.notes_imported = true
extracted = extractAnswersFromNotes(inline_notes)
for field in [problem, solution, target, mvp_scope]:
if extracted[field] is not null:
word_count = count_words(extracted[field])
if word_count > 15:
session.answers[field] = extracted[field]
session.completeness[field] = scoreCompleteness(extracted[field])
// Mark as partial if score is borderline (< 3) — needs targeted follow-up
session.notes_partial[field] = (scoreCompleteness(extracted[field]) < 3)
else:
// Too short to be reliable — mark for targeted follow-up
session.notes_partial[field] = true
// If extracted[field] is null, leave notes_partial[field] = false (no data → full question)
show_extraction_summary(extracted, session.language)
Extraction logic:
function extractAnswersFromNotes(notes):
extracted = {}
problem_keywords = ["문제", "불편", "pain", "problem", "struggle", "frustration",
"hours", "시간", "힘들", "어렵", "waste", "낭비"]
if contains_any(notes, problem_keywords):
extracted.problem = summarize_section(notes, "problem")
solution_keywords = ["unlike", "different", "vs", "compared", "대신", "차별점",
"unique", "only", "first", "유일", "특징", "instead"]
if contains_any(notes, solution_keywords):
extracted.solution = summarize_section(notes, "solution")
target_keywords = ["target", "user", "customer", "developer", "designer", "타겟",
"사용자", "개발자", "누구", "for ", "aimed at", "팀"]
if contains_any(notes, target_keywords):
extracted.target = summarize_section(notes, "target")
feature_keywords = ["feature", "must-have", "기능", "MVP", "v1", "v2",
"need to", "필요", "포함", "exclude", "핵심"]
if contains_any(notes, feature_keywords):
extracted.mvp_scope = summarize_section(notes, "mvp_scope")
return extracted
Show extraction summary before continuing.
For each field in the summary: if session.notes_partial[field] == true, append the reason in parentheses ("under 15 words" or "score < 3").
Korean:
"내용을 분석했습니다:
확인된 내용:
- 문제: [extracted.problem 요약, 최대 20단어] ← notes_partial.problem == true인 경우: "(부분 추출 — 추가 질문 예정: 15단어 미만 또는 점수 < 3)"
- 솔루션: [extracted.solution 요약] ← notes_partial.solution == true인 경우: "(부분 추출 — 추가 질문 예정)"
- 타겟: [extracted.target 요약] ← notes_partial.target == true인 경우: "(부분 추출 — 추가 질문 예정)"
- MVP 범위: [extracted.mvp_scope 요약] ← notes_partial.mvp_scope == true인 경우: "(부분 추출 — 추가 질문 예정)"
아직 확인이 필요한 내용: [null 필드 목록]
부분적으로 추출된 내용: [notes_partial=true 필드 목록 + 이유: 15단어 미만 또는 점수 < 3]
빠진 부분과 부분 추출된 부분만 추가로 질문드리겠습니다."
English:
"I analyzed your notes:
Extracted:
- Problem: [summary, max 20 words] ← if notes_partial.problem == true: "(partial — follow-up question coming: under 15 words or score < 3)"
- Solution: [summary] ← if notes_partial.solution == true: "(partial — follow-up question coming)"
- Target: [summary] ← if notes_partial.target == true: "(partial — follow-up question coming)"
- MVP scope: [summary] ← if notes_partial.mvp_scope == true: "(partial — follow-up question coming)"
Still need: [list of null fields]
Partial extracts (follow-up needed): [list of notes_partial=true fields with reason: under 15 words or score < 3]
I'll only ask about the missing or partial pieces."
Case B: Trigger is short (fewer than 50 words)
Do NOT ask whether the user has existing notes. Proceed directly to Step 3.
Skip condition: session.completeness.problem >= 3 AND session.notes_partial.problem == false
Targeted follow-up condition: session.completeness.problem >= 3 AND session.notes_partial.problem == true
→ In this case, skip the full question and ask only:
session.notes_partial.problem = false after handling.Ask as plain text output (do NOT call AskUserQuestion tool):
Korean:
이 제품이 해결하는 구체적인 문제는 무엇인가요?
타겟 사용자가 이 문제를 겪는 실제 상황을 설명해주세요.
(예: "매주 월요일 팀 미팅 때마다 누가 무엇을 했는지 파악하느라 30분을 낭비한다")
English:
What specific problem does this solve?
Describe a real situation where your target user faces this problem.
(e.g., "Every Monday standup, team leads spend 30 minutes just figuring out what everyone did last week")
Wait for the user's free-form response.
Completeness scoring (run after each answer):
function scoreCompleteness(answer):
score = 5
words = count_words(answer)
if words < 10: score = min(score, 1)
elif words < 20: score = min(score, 2)
generic_terms = ["better", "easier", "faster", "좋아", "편리", "빠르게",
"improve", "solve problems", "helps with", "도움이"]
if all_words_are_generic(answer, generic_terms):
score = min(score, 2)
specificity_markers = ["every", "매일", "매주", "minutes", "분", "hours",
"시간", "dollars", "원", "percent", "%", "~할 때"]
if contains_any(answer, specificity_markers):
score = min(score + 1, 5)
if has_concrete_example(answer): // quotes, named tools, specific scenarios
score = min(score + 1, 5)
return score
If score < 3 — ask ONE follow-up as plain text:
Korean: "좀 더 구체적으로 알려주세요. 실제 상황이나 수치를 포함해주시면 더 강력한 카피를 만들 수 있습니다."
English: "Could you be more specific? A concrete scenario or number (e.g., '2 hours wasted', '30% conversion drop') will make the copy much stronger."
Wait for response. Re-score.
If still score < 3 after follow-up: Accept the answer and append [TODO: add specific scenario with real numbers or situation]. Do not loop again.
session.answers.problem = answer // including [TODO] if applicable
session.completeness.problem = scoreCompleteness(answer)
session.notes_partial.problem = false // clear partial flag after interview step
Skip condition: session.completeness.solution >= 3 AND session.notes_partial.solution == false
Targeted follow-up condition: session.completeness.solution >= 3 AND session.notes_partial.solution == true
→ Skip the full question. Ask only (always include the hint regardless):
session.notes_partial.solution = false after handling.This is the highest-friction question for most users. Always include the hint example regardless of what the user has provided.
Ask as plain text:
Korean:
한 문장으로 솔루션을 설명해주세요. 기존 대안과 비교했을 때 무엇이 다른가요?
힌트: "X와 달리, 제 제품은 Y를 Z 방식으로 합니다."
예시: "Notion과 달리, 제 앱은 개발자의 GitHub 활동에서 자동으로 주간 리포트를 생성합니다."
English:
In one sentence: what makes this different from existing alternatives?
Hint: "Unlike X, my product does Y by Z."
Example: "Unlike Notion, my app automatically generates weekly reports from your team's GitHub activity — no manual updates needed."
If score < 3 — ask ONE follow-up:
Korean: "기존에 사람들이 어떻게 이 문제를 해결하고 있나요? 그리고 당신의 제품은 그것과 어떻게 다른가요?"
English: "How are people currently solving this problem? And what does your product do differently or better?"
If still < 3: Accept, append [TODO: clarify differentiation vs existing alternatives].
session.answers.solution = answer
session.completeness.solution = scoreCompleteness(answer)
session.notes_partial.solution = false
Skip condition: session.completeness.target >= 3 AND session.notes_partial.target == false
Targeted follow-up condition: session.completeness.target >= 3 AND session.notes_partial.target == true
→ Ask only:
session.notes_partial.target = false after handling.Ask as plain text:
Korean:
주요 타겟 사용자는 누구인가요?
역할, 현재 사용하는 도구나 방법, 그리고 가장 큰 불편함을 구체적으로 설명해주세요.
English:
Who is your primary user?
Describe their role, what tools or methods they currently use, and their biggest pain point.
If score < 3 — ask ONE follow-up:
Korean: "그 사람들이 지금 이 문제를 어떻게 해결하고 있나요? 어떤 도구나 방법을 쓰나요?"
English: "What do they use right now to handle this? Any specific tools or workarounds you've observed?"
If still < 3: Accept, append [TODO: define target user role and current tools more clearly].
session.answers.target = answer
session.completeness.target = scoreCompleteness(answer)
session.notes_partial.target = false
Skip condition: session.completeness.mvp_scope >= 3 AND session.notes_partial.mvp_scope == false
Targeted follow-up condition: session.completeness.mvp_scope >= 3 AND session.notes_partial.mvp_scope == true
→ Ask only:
session.notes_partial.mvp_scope = false after handling.Ask as plain text:
Korean:
MVP에서 반드시 있어야 하는 핵심 기능 3가지는 무엇인가요?
그리고 나중에 v2에서 추가해도 괜찮은 기능은 무엇인가요?
English:
What are the 3 must-have features for your MVP?
What can wait until v2?
If score < 3 — ask ONE follow-up:
Korean: "사용자가 처음 방문에서 반드시 경험해야 하는 핵심 가치가 무엇인가요? 그것을 가능하게 하는 기능은?"
English: "What's the single core value a first-time user must experience? What feature delivers that experience?"
If still < 3: Accept, append [TODO: define 3 MVP features explicitly].
session.answers.mvp_scope = answer
session.completeness.mvp_scope = scoreCompleteness(answer)
session.notes_partial.mvp_scope = false
After all 4 answers are collected, derive or confirm the product name.
candidates = extractProductNames(session.answers)
// Look for: capitalized proper nouns, quoted names, "called X", "named X", "제품명", "앱 이름"
if candidates is not empty:
// Confirm as plain text — then WAIT for user response before continuing
if session.language == "ko":
output "제품 이름이 '{candidates[0]}'인가요? 다른 이름이 있다면 알려주세요."
else:
output "Is the product name '{candidates[0]}'? Let me know if you have a different name."