Press Release Generator

Press Release Generator

FOR IMMEDIATE RELEASE

Your main announcement. Keep it strong, clear, and uppercase.

A brief, optional second line to add context to the headline.

Your city, state, and the date.

The first paragraph. It must summarize the entire press release (the 5 W's: Who, What, When, Where, Why).

The second paragraph. What problem does this solve? Why is this news important?

The third paragraph. How does your announcement address the problem? Provide details.

A powerful quote from a key person (e.g., CEO, Founder).

A standard, one-paragraph description of your company or organization.

Who should the media contact for more information?

Review your complete press release below. Go back to any tab to make edits.

Click "Next" or "Previous" to refresh this preview.

- ${escapeHTML(data.attribution)}

About ${inputs.boilerplate.value.split(' ')[0]}

${p(data.boilerplate)}

Contact:

${data.contactName ? `

${escapeHTML(data.contactName)}

` : ''} ${data.contactTitle ? `

${escapeHTML(data.contactTitle)}

` : ''} ${data.contactEmail ? `

${escapeHTML(data.contactEmail)}

` : ''} ${data.contactPhone ? `

${escapeHTML(data.contactPhone)}

` : ''} ${data.website ? `

${escapeHTML(data.website)}

` : ''}

###

`; }; const getTxtContent = () => { const data = getReleaseData(); let content = "FOR IMMEDIATE RELEASE\n\n"; content += `${data.headline.toUpperCase()}\n\n`; if (data.subheadline) { content += `${data.subheadline}\n\n`; } content += `${data.dateline} -- ${data.intro}\n\n`; content += `${data.problem}\n\n`; content += `${data.solution}\n\n`; content += `"${data.quote}"\n- ${data.attribution}\n\n`; content += `About\n${data.boilerplate}\n\n`; content += `Contact:\n`; if (data.contactName) content += `${data.contactName}\n`; if (data.contactTitle) content += `${data.contactTitle}\n`; if (data.contactEmail) content += `${data.contactEmail}\n`; if (data.contactPhone) content += `${data.contactPhone}\n`; if (data.website) content += `${data.website}\n`; content += `\n###\n`; return content; }; const downloadTxt = () => { const txtContent = getTxtContent(); const blob = new Blob([txtContent], { type: 'text/plain;charset=utf-8' }); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = 'press_release.txt'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(a.href); }; const downloadPDF = () => { if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF === 'undefined') { alert('Error: jsPDF library not loaded.'); return; } const { jsPDF } = window.jspdf; const doc = new jsPDF('p', 'mm', 'a4'); const data = getReleaseData(); const margin = 20; const pageWidth = doc.internal.pageSize.getWidth(); const usableWidth = pageWidth - (margin * 2); let yPos = 25; // Start position const addWrappedText = (text, options = {}) => { const { font = 'times', style = 'normal', size = 12, align = 'left', indent = 0, isQuote = false } = options; doc.setFont(font, style); doc.setFontSize(size); let textToSplit = text; let textMargin = margin + indent; let textWidth = usableWidth - indent; if (isQuote) { textMargin += 10; textWidth -= 20; textToSplit = `"${text}"`; } const splitText = doc.splitTextToSize(textToSplit, textWidth); if (yPos + (splitText.length * 7) > 270) { // Check for page break doc.addPage(); yPos = 20; } doc.text(splitText, textMargin, yPos, { align: align }); yPos += (splitText.length * 7); // 7mm per line yPos += 3; // buffer }; // --- Build PDF Document --- doc.setFont('times', 'bold'); doc.setFontSize(12); doc.text("FOR IMMEDIATE RELEASE", pageWidth / 2, yPos, { align: 'center' }); yPos += 10; doc.setFont('times', 'bold'); doc.setFontSize(16); addWrappedText(data.headline.toUpperCase(), { size: 16, style: 'bold', align: 'center' }); yPos += 2; if (data.subheadline) { addWrappedText(data.subheadline, { size: 12, style: 'italic', align: 'center' }); yPos += 2; } doc.setFont('times', 'normal'); doc.setFontSize(12); const datelineIntro = ` ${data.dateline} -- ${data.intro}`; addWrappedText(datelineIntro, { size: 12 }); addWrappedText(data.problem, { size: 12, indent: 5 }); addWrappedText(data.solution, { size: 12, indent: 5 }); addWrappedText(data.quote, { size: 12, style: 'italic', isQuote: true }); addWrappedText(`- ${data.attribution}`, { size: 12, style: 'bold', align: 'right' }); addWrappedText("About", { size: 12, style: 'bold' }); addWrappedText(data.boilerplate, { size: 12, indent: 5 }); addWrappedText("Contact:", { size: 12, style: 'bold' }); let contactInfo = ''; if (data.contactName) contactInfo += `${data.contactName}\n`; if (data.contactTitle) contactInfo += `${data.contactTitle}\n`; if (data.contactEmail) contactInfo += `${data.contactEmail}\n`; if (data.contactPhone) contactInfo += `${data.contactPhone}\n`; if (data.website) contactInfo += `${data.website}\n`; addWrappedText(contactInfo, { size: 12, indent: 5 }); addWrappedText("###", { size: 12, style: 'bold', align: 'center' }); doc.save('press_release.pdf'); }; // --- Event Listeners --- // Tab Buttons tabButtons.forEach((btn, index) => { btn.addEventListener('click', () => showTab(index + 1)); }); // Next/Prev Navigation nextBtn.addEventListener('click', () => showTab(currentTab + 1)); prevBtn.addEventListener('click', () => showTab(currentTab - 1)); // Tab 4 Actions downloadPdfBtn.addEventListener('click', downloadPDF); downloadTxtBtn.addEventListener('click', downloadTxt); // --- Initialization --- showTab(1); // Set initial state });
Scroll to Top