Why ×5 — なぜを重ねて核心を探す

公開日 · 更新日 · 6 MIN READ · 理解の記録

RECORD / 2025

WHYを5回繰り返すことで核心をみつける。

これってよく聞く話なんだけど、これをなんどもやれるように簡単なプログラムにしてみました。

Why × 5
コアに迫るためのツールだ。

Why1〜5 を順に入力 → 「まとめて出力」。ログ保存・コピー可能にしました。

Why ×5 — なぜを重ねて核心を探す

アプリの特徴

このミニアプリは、以下の機能を備えています。

  • テーマ入力
    解決したい問題や現象を1行で入力。
  • Why入力 ×5
    「なぜ?」を順に書いていける欄を用意。
    • Enter … 改行
    • Ctrl/⌘ + Enter … 次の欄へ
  • まとめて出力
    入力したWhyの流れをMarkdown形式に整形して一括表示。
  • コピー機能(多段フォールバック付き)
    • 通常:ワンクリックでクリップボードにコピー
    • ブラウザ制限時:自動で選択/手動コピー用モーダルが出る
  • ログ保存
    ローカルストレージに保存 → 過去のWhy×5を一覧表示し、読み込み・再編集も可能。
  • プリセット例
    • マーケティング(LPのCVR改善など)
    • プロダクト(継続率低下など)
    • 学習(習慣化できないなど)
      ワンクリックでサンプルを呼び出し、操作感をすぐ体験可能。

使い方(ステップごとに解説)

  1. テーマを書く
    例:「新規登録が伸びない」
  2. Why 1〜5を入力
    • Why1:直接の原因
    • Why2:その原因の理由
    • Why3〜5:さらに深掘り
      👉 最後は「根本原因の仮説」が見える
  3. まとめて出力
    • Markdown形式で一括整理
    • 「次の一手(仮説・実験・KPI)」も自動提案される
  4. 保存 & コピー
    • 保存:端末に残せるので、翌日や会議でも活用
    • コピー:ブログ記事やノートに貼り付けて共有可能

活用シーン

  • マーケティング戦略
    • LPのCVRが伸びない → Why ×5で根本原因を洗い出す
  • プロダクト開発
    • 継続率が下がっている → ユーザー体験の阻害要因を掘り下げる
  • 学習や自己改善
    • 習慣が続かない → 行動単位や環境設計に原因があることを特定

まとめ

「Why ×5 ミニアプリ」は、
👉 問いを量産し、磨き、記録として残せるシンプルな習慣ツール です。

付箋やノートに書くだけでは続かないフレームワークも、Webアプリにすると自然にログが貯まり、「問いの質」を日々磨けるようになります。

Why ×5 — 思考を「検証プラン」に変換する v1.5

手順:テーマ → Why1〜5+タグ反証条件(If/Then)根本仮説 → SMART → 出力/保存/コピー 15:00
入力後にまとめて出力できます。
※空ならWhy5を用いて自動で流し込みます。
📒 ログ(デバイス内に保存)
📝 出力フォーマット見本(Markdown)
# テーマ
- {{topic}}

## Why ×5(タグ付き)
1. {{w1}} — [{{t1}}]
2. {{w2}} — [{{t2}}]
3. {{w3}} — [{{t3}}]
4. {{w4}} — [{{t4}}]
5. {{w5}} — [{{t5}}]

## 反証条件(If / Then)
- IF {{if1}} THEN {{then1}}
- IF {{if2}} THEN {{then2}}

## 根本仮説(検証可能)
- {{hypothesis}}

## 次の一手(SMART)
- 行動:{{act}}
- 計測:{{metric}}
- 期間:{{period}}週間(〜{{deadline}})
- 成功基準:{{success}}
THEN
`; wrap.querySelector('.btn-del').onclick = ()=> wrap.remove(); ifthenList.appendChild(wrap); } addIfThen('奄美や長野で悪化した人が多い','水は原因ではない可能性'); addIfThen('食生活の変化が大きい','水以外の要因が主要因'); /* 入力で出力更新 */ [el.topic, el.w1, el.w2, el.w3, el.w4, el.w5, el.t1, el.t2, el.t3, el.t4, el.t5, hypoEl, actEl, metricEl, periodEl, successEl].forEach(n=> n.addEventListener('input', gen)); /* キー遷移(Enter/⌘Enter) */ const seq=[el.w1,el.w2,el.w3,el.w4,el.w5,hypoEl,actEl,metricEl,periodEl,successEl]; [el.topic, el.w1, el.w2, el.w3, el.w4, el.w5, hypoEl, actEl, metricEl, periodEl].forEach((node,i)=>{ node.addEventListener('keydown',e=>{ const isInput = node.tagName==='INPUT'; const next = ()=> seq[i+1]?.focus(); if(isInput && e.key==='Enter' && !e.shiftKey){ e.preventDefault(); next(); } if(!isInput && e.key==='Enter' && (e.ctrlKey||e.metaKey)){ e.preventDefault(); next(); } }); }); function sanitize(s){ return (s||'').toString().trim() } function deadlineFromWeeks(w){ const d=new Date(); d.setDate(d.getDate()+(Number(w)||0)*7); return d.toLocaleDateString(); } function val(){ const conds=[...ifthenList.querySelectorAll('.ifthen')].map(r=>({ if:sanitize(r.querySelector('.ifv').value), then:sanitize(r.querySelector('.thenv').value) })).filter(x=>x.if||x.then); return { topic:sanitize(el.topic.value), w1:sanitize(el.w1.value), w2:sanitize(el.w2.value), w3:sanitize(el.w3.value), w4:sanitize(el.w4.value), w5:sanitize(el.w5.value), t1:el.t1.value, t2:el.t2.value, t3:el.t3.value, t4:el.t4.value, t5:el.t5.value, hypothesis: sanitize(hypoEl.value) || sanitize(el.w5.value), act:sanitize(actEl.value), metric:sanitize(metricEl.value), period:sanitize(periodEl.value), success:sanitize(successEl.value), conds }; } function md(v){ const dl=deadlineFromWeeks(v.period||0); const why=[ `1. ${v.w1||'-'} — [${v.t1||'-'}]`, `2. ${v.w2||'-'} — [${v.t2||'-'}]`, `3. ${v.w3||'-'} — [${v.t3||'-'}]`, `4. ${v.w4||'-'} — [${v.t4||'-'}]`, `5. ${v.w5||'-'} — [${v.t5||'-'}]`, ].join('\n'); const ifthen=(v.conds.length? v.conds:[{if:'-',then:'-'}]).map(c=>`- IF ${c.if||'-'} THEN ${c.then||'-'}`).join('\n'); return [ `# テーマ - ${v.topic||'-'} ## Why ×5(タグ付き) ${why} ## 反証条件(If / Then) ${ifthen} ## 根本仮説(検証可能) - ${v.hypothesis||'-'} ## 次の一手(SMART) - 行動:${v.act||'-'} - 計測:${v.metric||'-'} - 期間:${v.period? v.period+'週間':'-'}(〜${v.period? dl:'-'}) - 成功基準:${v.success||'-'}` ].join('\n'); } function gen(){ el.out.textContent = md(val()); } /* コピー */ async function copyText(text){ if(navigator.clipboard && window.isSecureContext){ try{ await navigator.clipboard.writeText(text); dialogCopy('コピー成功'); return; }catch(e){} } try{ const ta=document.createElement('textarea'); ta.value=text; ta.setAttribute('readonly',''); ta.style.position='fixed'; ta.style.top='-1000px'; ta.style.opacity='0'; document.body.appendChild(ta); ta.focus(); ta.select(); const ok=document.execCommand('copy'); document.body.removeChild(ta); if(ok){ dialogCopy('コピー成功'); return; } }catch(e){} showCopyModal(text); dialogCopy('この環境では手動コピーのみ対応'); } function showCopyModal(text){ el.copyTextArea.value=text; el.copyModal.style.display='flex'; el.copyModal.setAttribute('aria-hidden','false'); el.copyTextArea.focus(); el.copyTextArea.select(); } $('#why5-copy-select').addEventListener('click',()=>{ el.copyTextArea.focus(); el.copyTextArea.select(); }); $('#why5-copy-close').addEventListener('click',()=>{ el.copyModal.style.display='none'; el.copyModal.setAttribute('aria-hidden','true'); }); function dialogCopy(msg){ let n=$('#copy-result'); if(!n){ n=document.createElement('div'); n.id='copy-result'; n.className='hint'; el.out.insertAdjacentElement('afterend', n); } n.textContent=msg; const aria=$('#copy-aria'); if(aria) aria.textContent=msg; } /* バリデーション(視認性向けにメッセージ簡潔化) */ function toast(msg){ let t=$('#why5-toast'); if(!t){ t=document.createElement('div'); t.id='why5-toast'; t.setAttribute('role','status'); t.style.cssText='position:fixed;left:50%;bottom:18px;transform:translateX(-50%);background:var(--panel);border:2px solid var(--border);color:var(--text);padding:12px 16px;border-radius:12px;z-index:9999;box-shadow:0 8px 20px rgba(2,8,23,.12);font-weight:800'; document.body.appendChild(t); } t.textContent=msg; t.style.opacity='1'; clearTimeout(t._to); t._to=setTimeout(()=>{ t.style.opacity='0'; }, 2000); } function guard(){ const v=val(); if(!v.topic){ toast('テーマは必須'); return false; } if(!v.w5){ toast('Why5(根本仮説)は必須'); return false; } if(!v.hypothesis){ toast('根本仮説(一文)は必須'); return false; } if(v.conds.length===0 || !v.conds[0].if || !v.conds[0].then){ toast('反証条件(If/Then)を1件以上'); return false; } return true; } /* 保存(localStorage + Cookie反映) */ const KEY='why5.logs.v1.3'; function readLogs(){ try{ return JSON.parse(localStorage.getItem(KEY)||'[]'); }catch(e){ return [] } } function writeLogs(arr){ localStorage.setItem(KEY, JSON.stringify(arr)) } function pruneIfTooLarge(arr){ try{ localStorage.setItem('__quota_test__','1'); localStorage.removeItem('__quota_test__'); return arr; } catch(e){ while(arr.length){ arr.pop(); try{ localStorage.setItem('__quota_test__','1'); localStorage.removeItem('__quota_test__'); break; }catch(_){}} return arr; } } function renderLogs(){ const logs=readLogs(); el.loglist.innerHTML=''; if(!logs.length){ el.loglist.innerHTML='
保存はまだありません。
'; return } logs.slice(0,50).forEach(it=>{ const row=document.createElement('div'); row.className='logitem'; row.innerHTML = `
${escapeHtml(it.topic||'(無題)')}
${new Date(it.date).toLocaleString()}
`; const act=document.createElement('div'); act.className='actions'; const loadB=btn('読み込む','secondary',()=>{ load(it); }); const copyB=btn('コピー','warn',async ()=>{ await copyText(md(it)); }); const delB=btn('削除','ghost',()=>{ del(it.id) }); act.append(loadB,copyB,delB); row.appendChild(act); el.loglist.appendChild(row); }); } function btn(label, cls, on){ const b=document.createElement('button'); b.textContent=label; if(cls) b.classList.add(cls); b.type='button'; b.onclick=on; return b } function load(it){ el.topic.value=it.topic||''; [el.w1,el.w2,el.w3,el.w4,el.w5].forEach((n,i)=> n.value=[it.w1,it.w2,it.w3,it.w4,it.w5][i]||''); [el.t1,el.t2,el.t3,el.t4,el.t5].forEach((n,i)=>{ [...n.options].forEach(o=>o.selected=(o.text===([it.t1,it.t2,it.t3,it.t4,it.t5][i]||'仮説'))); }); hypoEl.value = it.hypothesis||''; actEl.value = it.act||''; metricEl.value=it.metric||''; periodEl.value=it.period||''; successEl.value=it.success||''; ifthenList.innerHTML=''; (it.conds||[]).forEach(c=> addIfThen(c.if,c.then)); if(!it.conds || !it.conds.length) { addIfThen(); } gen(); toast('読み込み完了'); } function del(id){ const logs=readLogs().filter(x=>x.id!==id); writeLogs(logs); renderLogs(); toast('削除しました'); } function save(){ const v=val(); const item = { id:Date.now(), date:new Date().toISOString(), version:'1.5', ...v }; try{ const logs = readLogs(); logs.unshift(item); writeLogs(pruneIfTooLarge(logs)); updateHistory(v); renderRecentTopics(); renderCandidates(); renderLogs(); toast('保存しました'); } catch(e){ toast('保存に失敗:容量超過'); } } function escapeHtml(s){ return (s||'').replace(/[&"']/g, m=>({ '&':'&','':'>','"':'"','\'':''' }[m])) } /* タイマー(15分) */ let t=15*60; setInterval(()=>{ if(t{ [el.topic, el.w1, el.w2, el.w3, el.w4, el.w5, hypoEl, actEl, metricEl, periodEl, successEl].forEach(n=>n.value=''); ifthenList.innerHTML=''; addIfThen(); addIfThen(); el.out.textContent=''; toast('クリアしました'); }; el.save.onclick=()=>{ if(!guard()) return; gen(); save(); }; el.copy.onclick=async ()=>{ if(!guard()) return; gen(); await copyText(el.out.textContent); }; el.gen.onclick=()=>{ gen(); toast('更新しました'); }; /* 初期化 */ function init(){ loadUI(); renderLogs(); renderRecentTopics(); renderCandidates(); gen(); } init(); })();

コメントを残す