AI strategy tool · 8 minutes

Build a hyper-focused AI strategy.

Turn an expanding field of possibilities into one outcome, one strategic bet, and a short list of work that earns attention now.

The premise

You can do almost anything. You still cannot do everything.

AI is making previously difficult, expensive, or impossible work surprisingly easy. That expands the option set—but it does not expand your organisation's attention, trust, or capacity at the same rate. A useful AI strategy therefore begins with a specific outcome to drive toward. Technology is the lever; the outcome is the direction.

Strategy builder

Choose what winning means.

First choose the audience. The same strategic intent needs a different altitude, decision frame, and level of practicality at each layer.

Set the enterprise outcome, strategic bet, investment boundary, and executive accountability.

Outcome

Start with one result worth winning.

Everything else flows from a single, measurable outcome.

Proof

Make the outcome investable.

Connect the AI bet to enterprise value, a baseline, and a target executives can own.

The bet

Name the enterprise constraint AI will change.

Focus on the structural bottleneck—not the most interesting model capability.

Scope

Choose the smallest credible scope—or justify the ocean.

Ambition is welcome. Diffusion is not. Most strategies should start as a wedge; choose broader scope only when a smaller one would just move the bottleneck.

Boundaries

Set investment and accountability boundaries.

Every meaningful strategy declines some credible opportunities.

Review

You've made every call. Assemble the statement.

Your focused strategy appears in the panel. Adjust anything by stepping back, or generate again after a change.

`; const blob = new Blob([doc], { type: 'text/html' }); const url = URL.createObjectURL(blob); const slug = (value('beneficiary') || 'ai-strategy').toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 40) || 'ai-strategy'; const link = document.createElement('a'); link.href = url; link.download = `${slug}-strategy.html`; document.body.appendChild(link); link.click(); link.remove(); setTimeout(() => URL.revokeObjectURL(url), 1000); button.textContent = 'Downloaded'; setTimeout(() => button.textContent = 'Download', 1600); } async function copyStrategy() { const button = byId('copyStrategy'); const text = byId('result').innerText.replace(/Copy\s*Print \/ PDF\s*Download\s*$/, '').trim(); try { await navigator.clipboard.writeText(text); button.textContent = 'Copied'; setTimeout(() => button.textContent = 'Copy', 1600); } catch (error) { button.textContent = 'Select and copy'; } } function resetTool() { document.querySelectorAll('input[type="text"], textarea').forEach(input => input.value = ''); byId('advantage').value = 'speed'; document.querySelector('input[name="scope"][value="wedge"]').checked = true; byId('validation').style.display = 'none'; hasGenerated = false; try { localStorage.removeItem(STORAGE_KEY); } catch (e) {} goToStep(0); setPerspective(activePerspective); } /* ---------- Wizard navigation ---------- */ const steps = Array.from(document.querySelectorAll('.wizard-step')); const totalSteps = steps.length; let currentStep = 0; function buildProgressDots() { const container = byId('wizard-steps'); container.innerHTML = ''; for (let i = 0; i < totalSteps; i++) { const dot = document.createElement('div'); dot.className = 'wizard-step-dot'; container.appendChild(dot); } } function renderStep() { steps.forEach(step => step.classList.toggle('active', Number(step.dataset.step) === currentStep)); const dots = byId('wizard-steps').children; for (let i = 0; i < dots.length; i++) { dots[i].classList.toggle('current', i === currentStep); dots[i].classList.toggle('done', i < currentStep); } byId('wizard-count').textContent = `Step ${currentStep + 1} of ${totalSteps}`; byId('wizard-stage-name').textContent = steps[currentStep].dataset.stage; const back = byId('wizard-back'); const next = byId('wizard-next'); back.style.visibility = currentStep === 0 ? 'hidden' : 'visible'; next.style.display = currentStep === totalSteps - 1 ? 'none' : 'inline-flex'; } function goToStep(index) { currentStep = Math.max(0, Math.min(totalSteps - 1, index)); byId('validation').style.display = 'none'; renderStep(); saveState(); } // Lightweight per-step gate so the wizard nudges without blocking hard. const stepRequirements = { 0: [['outcome', 'single outcome'], ['beneficiary', 'beneficiary']], 1: [['metric', 'success metric'], ['target', 'target']], 2: [['bottleneck', 'critical bottleneck']] }; function validateStep(index) { const required = stepRequirements[index]; if (!required) return true; const missing = required.filter(([id]) => !value(id)).map(([, label]) => label); const validation = byId('validation'); if (missing.length) { validation.style.display = 'block'; validation.textContent = `Add the ${missing.join(' and ')} before continuing.`; return false; } validation.style.display = 'none'; return true; } /* ---------- Persistence ---------- */ const STORAGE_KEY = 'ai-strategy-focus.v1'; function collectState() { const fields = {}; ['outcome', 'beneficiary', 'deadline', 'metric', 'baseline', 'target', 'bottleneck', 'humanRole', 'assumption', 'notDoing'].forEach(id => { fields[id] = byId(id).value; }); const scopeEl = document.querySelector('input[name="scope"]:checked'); return { perspective: activePerspective, step: currentStep, hasGenerated, advantage: byId('advantage').value, scope: scopeEl ? scopeEl.value : 'wedge', fields }; } function saveState() { try { localStorage.setItem(STORAGE_KEY, JSON.stringify(collectState())); } catch (e) {} } function loadState() { let saved; try { saved = JSON.parse(localStorage.getItem(STORAGE_KEY)); } catch (e) { saved = null; } if (!saved) return false; if (saved.fields) { Object.entries(saved.fields).forEach(([id, val]) => { const el = byId(id); if (el) el.value = val || ''; }); } if (saved.advantage) byId('advantage').value = saved.advantage; if (saved.scope) { const scopeEl = document.querySelector(`input[name="scope"][value="${saved.scope}"]`); if (scopeEl) scopeEl.checked = true; } if (saved.perspective && perspectives[saved.perspective]) activePerspective = saved.perspective; if (typeof saved.step === 'number') currentStep = Math.max(0, Math.min(totalSteps - 1, saved.step)); hasGenerated = Boolean(saved.hasGenerated); return true; } /* ---------- Wiring ---------- */ document.querySelectorAll('.perspective-button').forEach(button => { button.addEventListener('click', () => setPerspective(button.dataset.perspective)); }); byId('wizard-next').addEventListener('click', () => { if (validateStep(currentStep)) goToStep(currentStep + 1); }); byId('wizard-back').addEventListener('click', () => goToStep(currentStep - 1)); byId('generate').addEventListener('click', createStrategy); byId('reset').addEventListener('click', resetTool); // Save answers as the user types / changes selections. byId('wizard-form').addEventListener('input', saveState); byId('wizard-form').addEventListener('change', saveState); /* ---------- Init ---------- */ buildProgressDots(); const restored = loadState(); setPerspective(activePerspective); renderStep();