SpeakFlow

Log in

Create account

Theme

Choose your viewing preference.

Our story

SpeakFlow was created to help learners overcome the pause, doubt, and silence that block real conversations. We turn practice into momentum with short, focused, and supportive lessons.

We started as a weekly meet-up in 2019. Today, SpeakFlow powers structured speaking practice for thousands of learners across time zones.

Mission and values

Milestones

Scrub the timeline
2019

First live speaking labs

We launched guided conversation rooms for small groups with real-time instructor cues.

Team

Instructors and curriculum designers collaborate to make practice engaging and practical.

Fluency warm-up

Use this quick drill before your next call: paraphrase and pace.

Target pace WPM 00:30

Get updates

Receive new drills and practice tips.

' : ''; host.replaceWith(fallback.firstChild); } } injectFragment('./header.html', 'header.k9s1q'); injectFragment('./footer.html', 'footer.p1v6t'); (function themeToggle(){ const btn = document.getElementById('themeToggle'); function setTheme(mode){ const root=document.documentElement; if(mode==='dark'){ root.classList.add('dark'); localStorage.setItem('sf_theme','dark'); } else if(mode==='light'){ root.classList.remove('dark'); localStorage.setItem('sf_theme','light'); } else { localStorage.removeItem('sf_theme'); } } btn.addEventListener('click', ()=>{ const isDark = document.documentElement.classList.contains('dark'); setTheme(isDark ? 'light' : 'dark'); }); })(); (function backToTop(){ const b = document.getElementById('backTop'); const onScroll = ()=>{ if(window.scrollY>400){ b.classList.remove('hidden'); } else { b.classList.add('hidden'); } }; window.addEventListener('scroll', onScroll, {passive:true}); b.addEventListener('click', ()=>{ window.scrollTo({top:0, behavior:'smooth'}); }); onScroll(); })(); (function cookies(){ const key='sf_cookie_choice'; const banner=document.getElementById('cookieBanner'); function show(){ banner.classList.remove('hidden'); } function hide(){ banner.classList.add('hidden'); } try{ const v=localStorage.getItem(key); if(!v){ setTimeout(show, 600); } }catch(e){} document.getElementById('cookieAccept').addEventListener('click',()=>{ try{localStorage.setItem(key,'accepted');}catch(e){} hide(); }); document.getElementById('cookieReject').addEventListener('click',()=>{ try{localStorage.setItem(key,'rejected');}catch(e){} hide(); }); })(); (function valuesModal(){ const modal=document.getElementById('valuesModal'); const title=document.getElementById('valuesTitle'); const body=document.getElementById('valuesBody'); const mapping={ clarity:{ t:'Clarity', b:'We refine prompts and responses into crisp, listener-friendly lines. Expect short sentences, explicit structure, and confident delivery.' }, momentum:{ t:'Momentum', b:'We stack micro-wins: 2–3 minute drills, immediate feedback, and simple targets that make steady practice feel rewarding.' }, inclusivity:{ t:'Inclusivity', b:'We celebrate accents and diverse experience. The goal is communication that lands: respectful, efficient, and human.' } }; function open(kind){ const m=mapping[kind]; if(!m) return; title.textContent=m.t; body.textContent=m.b; modal.classList.remove('hidden'); modal.classList.add('flex'); document.body.style.overflow='hidden'; } function close(){ modal.classList.add('hidden'); modal.classList.remove('flex'); document.body.style.overflow=''; } document.querySelectorAll('[data-open-values]').forEach(btn=>{ btn.addEventListener('click',()=>open(btn.getAttribute('data-open-values'))); }); document.getElementById('valuesClose').addEventListener('click',close); modal.addEventListener('click',e=>{ if(e.target===modal) close(); }); document.addEventListener('keydown',e=>{ if(e.key==='Escape') close(); }); })(); (function teamModal(){ const modal=document.getElementById('teamModal'); const nameEl=document.getElementById('teamName'); const titleEl=document.getElementById('teamTitle'); const bioEl=document.getElementById('teamBio'); function open(data){ nameEl.textContent=data.name; titleEl.textContent=data.title; bioEl.textContent=data.bio; modal.classList.remove('hidden'); modal.classList.add('flex'); document.body.style.overflow='hidden'; } function close(){ modal.classList.add('hidden'); modal.classList.remove('flex'); document.body.style.overflow=''; } document.querySelectorAll('[data-team]').forEach(b=>{ b.addEventListener('click',()=>{ try{ open(JSON.parse(b.getAttribute('data-team'))); }catch(e){} }); }); document.getElementById('teamClose').addEventListener('click',close); modal.addEventListener('click',e=>{ if(e.target===modal) close(); }); document.addEventListener('keydown',e=>{ if(e.key==='Escape') close(); }); })(); (function timeline(){ const events=[ {year:2019, title:'First live speaking labs', desc:'We launched guided conversation rooms for small groups with real-time instructor cues.'}, {year:2021, title:'Feedback loops v2', desc:'We introduced actionable feedback focusing on pace, turn-taking, and listener signals.'}, {year:2024, title:'Speaking metrics', desc:'We added clarity and comfort metrics to help learners track steady improvements.'} ]; const range=document.getElementById('timelineRange'); const label=document.getElementById('yearLabel'); const details=document.getElementById('timelineDetails'); const dots=[...document.querySelectorAll('.timeline-dot')]; let autoplay=null; function render(i){ const ev=events[i]; label.textContent=ev.year; details.innerHTML='

'+ev.title+'

'+ev.desc+'

'; dots.forEach((d,idx)=>{ const dot=d.querySelector('span'); if(idx<=i){ dot.classList.remove('bg-slate-300','dark:bg-slate-600'); dot.classList.add('bg-indigo-500'); d.classList.add('border-indigo-400'); } else { dot.classList.remove('bg-indigo-500'); dot.classList.add('bg-slate-300','dark:bg-slate-600'); d.classList.remove('border-indigo-400'); } }); } range.addEventListener('input',()=>render(parseInt(range.value,10))); dots.forEach((d,idx)=>d.addEventListener('click',()=>{ range.value=idx; render(idx); })); document.getElementById('resetTimelineBtn').addEventListener('click',()=>{ range.value=0; render(0); stopAuto(); }); function startAuto(){ stopAuto(); let i=parseInt(range.value,10); autoplay=setInterval(()=>{ i=(i+1)%events.length; range.value=i; render(i); }, 2200); apBtn.textContent='Stop'; } function stopAuto(){ if(autoplay){ clearInterval(autoplay); autoplay=null; } apBtn.textContent='Auto-play'; } const apBtn=document.getElementById('autoPlayBtn'); apBtn.addEventListener('click',()=>{ autoplay?stopAuto():startAuto(); }); render(0); })(); (function warmup(){ const variants = [ "Let me restate it simply:", "In other words, you're saying:", "To make sure I’m aligned:", "So the key point is:" ]; const prompts=[ "Summarize your main goal for this week.", "Explain a recent decision you made at work.", "Describe your favorite book in one sentence.", "Share one improvement you want in your meetings." ]; const input=document.getElementById('warmupInput'); const out=document.getElementById('warmupOut'); const btn=document.getElementById('warmupBtn'); const shuffle=document.getElementById('shufflePrompt'); const start=document.getElementById('startDrill'); const stop=document.getElementById('stopDrill'); const time=document.getElementById('drillTime'); const pace=document.getElementById('paceInput'); let ticker=null, countdown=null, left=30; function paraphrase(){ const txt = input.value.trim(); const pick = variants[Math.floor(Math.random()*variants.length)]; out.textContent = txt ? pick+" "+txt : "Try adding a sentence above. Then paraphrase with a calm pace."; } btn.addEventListener('click', paraphrase); shuffle.addEventListener('click', ()=>{ input.value=prompts[Math.floor(Math.random()*prompts.length)]; paraphrase(); }); function format(s){ return '00:'+(s<10?('0'+s):s); } function pulse(){ const spm=parseInt(pace.value,10); if(isNaN(spm)||spm<60||spm>180) return; const interval=60000/spm; // ms per word const flash=document.createElement('div'); flash.className='mt-3 w-full h-2 rounded-full bg-slate-200 dark:bg-slate-700 overflow-hidden'; const bar=document.createElement('div'); bar.className='h-full bg-indigo-500 transition-all'; flash.appendChild(bar); out.appendChild(flash); let on=true; ticker=setInterval(()=>{ if(!document.body.contains(flash)){ clearInterval(ticker); ticker=null; return; } bar.style.width = on?'100%':'10%'; bar.style.opacity = on? '1' : '0.5'; on=!on; }, interval); } function startDrill(){ if(ticker||countdown) return; left=30; time.textContent=format(left); out.textContent='Speak for 30 seconds. Match the pace pulses. Keep sentences short.'; pulse(); countdown=setInterval(()=>{ left--; time.textContent=format(left); if(left<=0){ stopDrill(); out.textContent='Great job. Quick reflection: What felt easy? What would you tweak next time?'; } }, 1000); start.classList.add('hidden'); stop.classList.remove('hidden'); } function stopDrill(){ if(ticker){ clearInterval(ticker); ticker=null; } if(countdown){ clearInterval(countdown); countdown=null; } time.textContent='00:30'; start.classList.remove('hidden'); stop.classList.add('hidden'); } start.addEventListener('click', startDrill); stop.addEventListener('click', stopDrill); pace.addEventListener('change', ()=>{ if(ticker){ stopDrill(); startDrill(); } }); })(); (function emailCapture(){ const email=document.getElementById('emailInput'); const btn=document.getElementById('emailSubmit'); const msg=document.getElementById('emailMsg'); function valid(v){ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v); } try{ const saved = localStorage.getItem('sf_email'); if(saved){ email.value=saved; msg.textContent='Thanks — you are already subscribed.'; msg.className='mt-2 text-sm text-emerald-600'; } }catch(e){} btn.addEventListener('click', ()=>{ const v=email.value.trim(); if(!valid(v)){ msg.textContent='Please enter a valid email address.'; msg.className='mt-2 text-sm text-red-600'; email.focus(); return; } try{ localStorage.setItem('sf_email', v); }catch(e){} msg.textContent='Subscribed! You will receive practice tips soon.'; msg.className='mt-2 text-sm text-emerald-600'; }); })();