Romance Story Idea Generator

Romance Story Idea Generator

Spark your next love story by defining the core elements.

Protagonist A

Protagonist B

Personality: ${idea.bTrait}

Secret/Fear: ${idea.bSecret}

The Setup

Trope: ${idea.trope}

Setting: ${idea.setting}

The Conflict

Internal: ${idea.internal}

External: ${idea.external}

`; const contentDiv = document.getElementById('generated-idea-content'); if (contentDiv) { contentDiv.innerHTML = ideaHTML; lucide.createIcons(); } } tabs.forEach((tab, index) => tab.addEventListener('click', () => updateTabUI(index))); nextBtn.addEventListener('click', () => { if (currentTab < totalTabs - 1) { if (currentTab === totalTabs - 2) generateIdea(); updateTabUI(currentTab + 1); } }); prevBtn.addEventListener('click', () => { if (currentTab > 0) updateTabUI(currentTab - 1); }); downloadPdfBtn.addEventListener('click', () => { const { jsPDF } = window.jspdf; const doc = new jsPDF({ orientation: 'portrait', unit: 'mm', format: 'a4' }); const getValue = id => document.getElementById(id)?.value.trim() || 'Not Provided'; const idea = { aJob: getValue('lover-a-job'), aTrait: getValue('lover-a-trait'), aSecret: getValue('lover-a-secret'), bJob: getValue('lover-b-job'), bTrait: getValue('lover-b-trait'), bSecret: getValue('lover-b-secret'), trope: getValue('setup-trope'), setting: getValue('setup-setting'), internal: getValue('conflict-internal'), external: getValue('conflict-external'), }; const logline = `A ${idea.aTrait} ${idea.aJob} and an ${idea.bTrait} ${idea.bJob} must overcome ${idea.external.toLowerCase()} and their own inner demons—${idea.internal.toLowerCase()}—as they fall in love.`; const pageW = doc.internal.pageSize.getWidth(); const pageH = doc.internal.pageSize.getHeight(); const margin = 20; const usableWidth = pageW - margin * 2; let y = 0; const roseColor = '#E11D48'; const darkGrayColor = '#374151'; const lightGrayColor = '#6B7280'; const addFooter = () => { const pageCount = doc.internal.getNumberOfPages(); for (let i = 1; i <= pageCount; i++) { doc.setPage(i); doc.setFontSize(9); doc.setTextColor(lightGrayColor); doc.text(`Romance Story Idea | Page ${i} of ${pageCount}`, pageW / 2, pageH - 10, { align: 'center' }); } }; const checkPageBreak = (height) => { if (y + height >= pageH - margin) { doc.addPage(); y = margin; } }; const addSectionHeader = (text) => { checkPageBreak(20); y += 12; doc.setFontSize(16); doc.setFont(undefined, 'bold'); doc.setTextColor(roseColor); doc.text(text, margin, y); y += 6; }; const addContent = (label, value) => { const valueLines = doc.splitTextToSize(value, usableWidth); const heightNeeded = (valueLines.length * 5) + 8; checkPageBreak(heightNeeded); doc.setFontSize(11); doc.setFont(undefined, 'bold'); doc.setTextColor(darkGrayColor); doc.text(label, margin, y); y += 5; doc.setFont(undefined, 'normal'); doc.setTextColor(lightGrayColor); doc.text(valueLines, margin + 2, y); y += valueLines.length * 5 + 3; }; // --- Build PDF --- // Title y = margin + 15; doc.setFontSize(26); doc.setFont(undefined, 'bold'); doc.setTextColor(darkGrayColor); doc.text('Romance Story Idea', pageW / 2, y, { align: 'center' }); y += 15; // Logline doc.setFillColor(254, 242, 242); // rose-50 doc.rect(margin-5, y, usableWidth+10, 30, 'F'); doc.setFontSize(11); doc.setFont(undefined, 'italic'); doc.setTextColor(roseColor); const loglineLines = doc.splitTextToSize(logline, usableWidth); doc.text(loglineLines, pageW/2, y + 10, {align: 'center'}); y += 40; // Content addSectionHeader('The Lovers'); addContent('Protagonist A: The ' + idea.aJob, `Trait: ${idea.aTrait}\nSecret/Fear: ${idea.aSecret}`); y += 2; addContent('Protagonist B: The ' + idea.bJob, `Trait: ${idea.bTrait}\nSecret/Fear: ${idea.bSecret}`); addSectionHeader('The Setup'); addContent('Primary Trope:', idea.trope); addContent('Setting:', idea.setting); addSectionHeader('The Conflict'); addContent('Internal Conflict:', idea.internal); addContent('External Conflict:', idea.external); addFooter(); doc.save('Romance-Story-Idea.pdf'); }); updateTabUI(0); lucide.createIcons(); });
Scroll to Top