πAI Twitter Thread Maker
Create viral Twitter threads instantly with AI! Generate engaging, SEO-optimized threads with viral hooks, emoji integration, and real-time character counting. No login required - start creating viral content now!
π€ What Is a Twitter Thread Generator?
Think of a Twitter thread like a digital storytelling staircase - each tweet leads perfectly to the next! This AI tool transforms your ideas into engaging, viral-ready Twitter threads complete with hooks, emojis, and perfect character counts. No more struggling to break up your thoughts or losing followers mid-story!
π₯ Viral Thread Templates
β‘ Productivity Tips
10 habits that changed my life in 90 days
πΌ Business Lessons
5 mistakes I made building my startup
π» Tech Insights
Why AI will change everything in 2025
π Personal Growth
How I overcame fear and built confidence
π Marketing Strategy
7 growth hacks that got me 10K followers
π° Finance Tips
How to save $10K in 12 months
${formatTweetContent(tweet)}
π¬ ${Math.floor(Math.random() * 50)}
π ${Math.floor(Math.random() * 100)}
β€οΈ ${Math.floor(Math.random() * 200)}
π ${Math.floor(Math.random() * 1000)}
`;
previewContainer.appendChild(tweetDiv);
});
}
function formatTweetContent(content) {
return content
.replace(/(#\w+)/g, '$1')
.replace(/(@\w+)/g, '$1')
.replace(/(https?:\/\/[^\s]+)/g, '$1');
}
function updateTweetPreview(index) {
const input = document.getElementById(`tweet-${index}`);
if (input) {
currentThread[index] = input.value;
updateCharCounter(index);
updateThreadPreview();
updateAnalytics();
}
}
function updateCharCounter(index) {
const input = document.getElementById(`tweet-${index}`);
const counter = document.getElementById(`counter-${index}`);
if (input && counter) {
const length = input.value.length;
counter.textContent = `${length}/280`;
if (length > 280) {
counter.className = 'char-counter error';
} else if (length > 250) {
counter.className = 'char-counter warning';
} else {
counter.className = 'char-counter';
}
}
}
function updateAnalytics() {
const totalChars = currentThread.reduce((sum, tweet) => sum + tweet.length, 0);
const avgChars = Math.round(totalChars / currentThread.length);
const emojiCount = currentThread.join('').match(/[\u{1F600}-\u{1F64F}]|[\u{1F300}-\u{1F5FF}]|[\u{1F680}-\u{1F6FF}]|[\u{1F1E0}-\u{1F1FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]/gu)?.length || 0;
const hashtagCount = currentThread.join('').match(/#\w+/g)?.length || 0;
// Calculate viral score based on various factors
const viralScore = calculateViralScore();
document.getElementById('totalChars').textContent = totalChars;
document.getElementById('avgChars').textContent = avgChars;
document.getElementById('emojiCount').textContent = emojiCount;
document.getElementById('hashtagCount').textContent = hashtagCount;
document.getElementById('engagementScore').textContent = viralScore;
}
function calculateViralScore() {
let score = 0;
// Thread length optimization (5-7 tweets ideal)
const length = currentThread.length;
if (length >= 5 && length <= 7) score += 25;
else if (length >= 3 && length <= 10) score += 15;
else score += 5;
// Hook quality (first tweet)
const firstTweet = currentThread[0] || '';
if (firstTweet.includes('?')) score += 10;
if (firstTweet.length < 240) score += 10;
if (/^\d+/.test(firstTweet) || firstTweet.includes('thread')) score += 15;
// Engagement elements
const allText = currentThread.join(' ');
if (allText.includes('?')) score += 10;
if (allText.includes('!')) score += 5;
if (allText.match(/#\w+/g)?.length > 0) score += 10;
if (allText.match(/[\u{1F600}-\u{1F64F}]|[\u{1F300}-\u{1F5FF}]/gu)?.length > 3) score += 15;
// Structure bonus
if (currentThread.some(tweet => /^\d+\//.test(tweet))) score += 15;
return Math.min(score, 100);
}
function addTweet() {
currentThread.push('New tweet content...');
displayThreadEditor();
updateThreadPreview();
updateAnalytics();
}
// ========== EXPORT FUNCTIONS ==========
function copyThread() {
const threadText = currentThread.map((tweet, index) => `${index + 1}/${currentThread.length}\n${tweet}`).join('\n\n');
navigator.clipboard.writeText(threadText).then(() => {
document.getElementById('exportStatus').textContent = 'Thread copied to clipboard!';
showNotification('Thread copied successfully!', 'success');
}).catch(() => {
// Fallback for older browsers
const textArea = document.createElement('textarea');
textArea.value = threadText;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);
document.getElementById('exportStatus').textContent = 'Thread copied to clipboard!';
showNotification('Thread copied successfully!', 'success');
});
}
function exportToJSON() {
const threadData = {
topic: document.getElementById('threadTopic').value,
createdAt: new Date().toISOString(),
tweets: currentThread,
analytics: {
totalChars: currentThread.reduce((sum, tweet) => sum + tweet.length, 0),
avgChars: Math.round(currentThread.reduce((sum, tweet) => sum + tweet.length, 0) / currentThread.length),
emojiCount: currentThread.join('').match(/[\u{1F600}-\u{1F64F}]|[\u{1F300}-\u{1F5FF}]/gu)?.length || 0,
hashtagCount: currentThread.join('').match(/#\w+/g)?.length || 0,
viralScore: calculateViralScore()
}
};
const blob = new Blob([JSON.stringify(threadData, null, 2)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `twitter-thread-${Date.now()}.json`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
document.getElementById('exportStatus').textContent = 'Thread exported as JSON!';
showNotification('Thread exported successfully!', 'success');
}
// ========== SAMPLE FUNCTIONS ==========
function useSample(sampleType) {
const template = THREAD_TEMPLATES[sampleType];
if (!template) return;
document.getElementById('threadTopic').value = template.topic;
// Set appropriate thread length
document.getElementById('threadLength').value = template.content.length + 2; // +2 for hook and CTA
// Auto-generate with template
setTimeout(() => generateThread(), 100);
// Smooth scroll to generator
document.getElementById('generateBtn').scrollIntoView({
behavior: 'smooth',
block: 'center'
});
}
// ========== UTILITY FUNCTIONS ==========
// Show notification toast
function showNotification(message, type = 'success') {
const toast = document.createElement('div');
toast.className = `toast ${type}`;
toast.textContent = message;
document.body.appendChild(toast);
setTimeout(() => {
toast.remove();
}, 3000);
}
// Show OTA section
function showOTA() {
const otaContainer = document.getElementById('otaContainer');
if (otaContainer && (otaContainer.style.display === 'none' || !otaContainer.style.display)) {
otaContainer.style.display = 'block';
// Update message for content creators
const otaHeader = document.querySelector('.ota-header h3');
const otaText = document.querySelector('.ota-header p');
if (otaHeader && otaText) {
otaHeader.textContent = 'π Ready to Share Your Viral Content?';
otaText.textContent = 'Planning to travel for content creation or business meetings? Find the best deals worldwide!';
}
}
}
// Analytics tracking
function trackEvent(eventName, data = {}) {
if (typeof gtag !== 'undefined') {
gtag('event', eventName, {
'event_category': TOOL_CONFIG.category,
'event_label': TOOL_CONFIG.name,
...data
});
}
}
// ========== AI ASSISTANT FUNCTIONS ==========
// AI λͺ¨λ¬ μ΄κΈ°
function openAIModal() {
const modal = document.getElementById('aiModal');
if(modal) modal.classList.add('show');
if (aiModalState.apiKey && aiModalState.currentView === 'gemini') {
showGeminiChat();
} else {
showAISelector();
}
updateAPIKeyStatus();
}
// AI λͺ¨λ¬ λ«κΈ°
function closeAIModal() {
const modal = document.getElementById('aiModal');
if(modal) modal.classList.remove('show');
setTimeout(() => {
aiModalState.currentView = 'selector';
showAISelector();
}, 300);
}
// AI μ ν νλ©΄ νμ
function showAISelector() {
document.getElementById('aiModalTitle').textContent = 'Choose Your AI Assistant';
document.getElementById('aiSelector').style.display = 'flex';
document.getElementById('geminiChat').style.display = 'none';
document.getElementById('apiKeySetup').style.display = 'none';
aiModalState.currentView = 'selector';
}
// Gemini μ±ν
νλ©΄ νμ
function showGeminiChat() {
document.getElementById('aiModalTitle').innerHTML = 'β¨ Gemini AI Assistant';
document.getElementById('aiSelector').style.display = 'none';
document.getElementById('geminiChat').style.display = 'flex';
document.getElementById('apiKeySetup').style.display = 'none';
aiModalState.currentView = 'gemini';
const chatMessages = document.getElementById('chatMessages');
if (!chatMessages.innerHTML.trim()) {
addMessage('assistant', `Hello! I can help you with:
β’ Creating viral Twitter thread ideas
β’ Improving your thread engagement
β’ Optimizing content for different audiences
β’ Finding trending topics in your niche
β’ Writing compelling hooks and CTAs
What would you like help with for your Twitter threads?`);
}
}
// API ν€ μ€μ νλ©΄ νμ
function showAPIKeySetup() {
document.getElementById('aiModalTitle').textContent = 'Setup Gemini API';
document.getElementById('aiSelector').style.display = 'none';
document.getElementById('geminiChat').style.display = 'none';
document.getElementById('apiKeySetup').style.display = 'block';
aiModalState.currentView = 'setup';
}
// AI μ ν μ²λ¦¬
function selectAI(aiType) {
switch(aiType) {
case 'chatgpt':
const toolContext = `I need help creating viral Twitter threads. I'm using a Twitter Thread Maker tool and want to improve my content strategy and engagement.`;
const chatUrl = `https://chat.openai.com/?q=${encodeURIComponent(toolContext)}`;
window.open(chatUrl, '_blank');
closeAIModal();
trackEvent('ai_selection', { ai_type: 'chatgpt' });
break;
case 'claude':
const claudeContext = `I need help creating viral Twitter threads. I'm using a Twitter Thread Maker tool and want to improve my content strategy and engagement.`;
const claudeUrl = `https://claude.ai/chat?q=${encodeURIComponent(claudeContext)}`;
window.open(claudeUrl, '_blank');
closeAIModal();
trackEvent('ai_selection', { ai_type: 'claude' });
break;
case 'gemini':
if (!aiModalState.apiKey) {
showAPIKeySetup();
} else {
showGeminiChat();
}
trackEvent('ai_selection', { ai_type: 'gemini' });
break;
}
}
// API ν€ μ μ₯
function saveGeminiApiKey() {
const apiKey = document.getElementById('geminiApiKeyInput').value.trim();
if (apiKey) {
localStorage.setItem('geminiApiKey', apiKey);
aiModalState.apiKey = apiKey;
showGeminiChat();
updateAPIKeyStatus();
} else {
alert('Please enter a valid API key');
}
}
// API ν€ μν μ
λ°μ΄νΈ
function updateAPIKeyStatus() {
const statusEl = document.getElementById('apiKeyStatus');
if (aiModalState.apiKey) {
statusEl.innerHTML = 'Change API Key';
} else {
statusEl.textContent = 'No API key set';
}
}
// μ±ν
λ©μμ§ μΆκ°
function addMessage(type, content) {
const chatMessages = document.getElementById('chatMessages');
const messageDiv = document.createElement('div');
messageDiv.className = `message ${type}`;
if (type === 'user') {
messageDiv.innerHTML = `You: ${content}`;
} else {
messageDiv.innerHTML = `β¨ Gemini:${content.replace(/\n/g, '
')}`; } chatMessages.appendChild(messageDiv); chatMessages.scrollTop = chatMessages.scrollHeight; } // Geminiμ λ©μμ§ μ μ‘ async function sendToGemini() { const input = document.getElementById('geminiInput'); const message = input.value.trim(); if (!message) return; addMessage('user', message); input.value = ''; const loadingMsg = document.createElement('div'); loadingMsg.className = 'message assistant'; loadingMsg.innerHTML = 'β¨ Gemini:
Thinking...'; loadingMsg.id = 'loading-message'; document.getElementById('chatMessages').appendChild(loadingMsg); try { const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=${aiModalState.apiKey}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ contents: [{ parts: [{ text: `Context: User is using a Twitter Thread Maker tool to create viral content. Help them with: - Thread ideas and viral hooks - Content optimization for engagement - Twitter best practices and strategy - Trending topics and hashtag suggestions - Writing compelling openings and CTAs Current thread topic: "${document.getElementById('threadTopic').value || 'Not set'}" User question: ${message}` }] }], generationConfig: { temperature: 0.7, maxOutputTokens: 1000 } }) }); const data = await response.json(); document.getElementById('loading-message').remove(); if (data.candidates && data.candidates[0] && data.candidates[0].content) { const reply = data.candidates[0].content.parts[0].text; addMessage('assistant', reply); } else { addMessage('assistant', 'Sorry, I could not generate a response. Please try again.'); } } catch (error) { document.getElementById('loading-message')?.remove(); if (error.message.includes('API key')) { addMessage('error', 'Invalid API key. Please check your API key and try again.'); showAPIKeySetup(); } else { addMessage('error', 'Failed to connect to Gemini. Please check your internet connection and try again.'); } } } // ========== EVENT LISTENERS ========== document.addEventListener('DOMContentLoaded', function() { // Thread topic enter key const topicInput = document.getElementById('threadTopic'); if (topicInput) { topicInput.addEventListener('keypress', function(e) { if (e.key === 'Enter') { generateThread(); } }); } // AI λ²νΌ μ΄λ²€νΈ document.getElementById('aiBtn').addEventListener('click', openAIModal); // λͺ¨λ¬ μΈλΆ ν΄λ¦μ λ«κΈ° document.getElementById('aiModal').addEventListener('click', function(e) { if (e.target === this) { closeAIModal(); } }); // μν° ν€ μ§μ λ° ESC ν€λ‘ λͺ¨λ¬ λ«κΈ° document.addEventListener('keydown', function(e) { if (e.key === 'Enter') { const geminiInput = document.getElementById('geminiInput'); if (document.activeElement === geminiInput) { sendToGemini(); } } if (e.key === 'Escape') { closeAIModal(); } }); updateAPIKeyStatus(); updateCurrentYear(); updateToolCount(); }); // ========== DYNAMIC TOOL COUNT ========== async function updateToolCount() { try { const response = await fetch('/api/tool-count.php'); const data = await response.json(); document.querySelectorAll('.dynamic-tools-count').forEach(el => { el.textContent = `${data.count}+ free online tools in 211 languages. No signup, no fees, just tools that work.`; }); document.querySelectorAll('.dynamic-count').forEach(el => { const prefix = el.getAttribute('data-text') || ''; const suffix = el.getAttribute('data-suffix') || ''; const icon = el.textContent.split(' ')[0] || ''; el.textContent = `${icon} ${prefix} ${data.count}+ ${suffix}`; }); } catch (error) { const fallbackCount = 333; document.querySelectorAll('.dynamic-tools-count').forEach(el => { el.textContent = `${fallbackCount}+ free online tools in 211 languages. No signup, no fees, just tools that work.`; }); document.querySelectorAll('.dynamic-count').forEach(el => { const prefix = el.getAttribute('data-text') || ''; const suffix = el.getAttribute('data-suffix') || ''; const icon = el.textContent.split(' ')[0] || ''; el.textContent = `${icon} ${prefix} ${fallbackCount}+ ${suffix}`; }); } } function updateCurrentYear() { const currentYear = new Date().getFullYear(); document.querySelectorAll('.current-year').forEach(el => { el.textContent = currentYear; }); } // ========== ANALYTICS ========== window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-XXXXXXXXX'); trackEvent('page_view', { tool: TOOL_CONFIG.name, category: TOOL_CONFIG.category });