Portfolio Layout Planner Generator

Portfolio Layout Planner

Portfolio Layout Planner

Design your portfolio's structure and download the plan.

Live Preview

${skill}

`).join('')}
`; } const contactHtml = `
`; livePreview.innerHTML = `
${heroHtml}

${projects.title}

${projectsHtml}

${skills.title}

${skillsHtml}

${contact.title}

${contactHtml}
`; } function updateConfigAndRender() { portfolioConfig.global.font = controls.font.value; portfolioConfig.hero.headline = controls.heroHeadline.value; portfolioConfig.hero.subheading = controls.heroSubheading.value; portfolioConfig.hero.layout = controls.heroLayout.value; portfolioConfig.projects.title = controls.projectsTitle.value; portfolioConfig.projects.layout = controls.projectsLayout.value; portfolioConfig.projects.count = parseInt(controls.projectsCount.value, 10); portfolioConfig.skills.title = controls.skillsTitle.value; portfolioConfig.skills.list = controls.skillsList.value; portfolioConfig.skills.layout = controls.skillsLayout.value; portfolioConfig.contact.title = controls.contactTitle.value; portfolioConfig.contact.text = controls.contactText.value; renderPreview(); } Object.values(controls).forEach(control => { if (control.id !== 'palette-selector' && control.id !== 'download-plan') { control.addEventListener('input', updateConfigAndRender); } }); controls.palette.addEventListener('click', (e) => { if (e.target.classList.contains('color-swatch')) { controls.palette.querySelectorAll('.color-swatch').forEach(sw => sw.classList.remove('selected')); e.target.classList.add('selected'); portfolioConfig.global.palette.bg = e.target.dataset.bg; portfolioConfig.global.palette.primary = e.target.dataset.primary; renderPreview(); } }); document.querySelectorAll('.accordion-button').forEach(button => { button.addEventListener('click', () => { const isActive = button.classList.contains('active'); document.querySelectorAll('.accordion-button').forEach(btn => btn.classList.remove('active')); if (!isActive) { button.classList.add('active'); } }); }); controls.downloadBtn.addEventListener('click', () => { if (typeof jspdf === 'undefined' || !jspdf.jsPDF) { alert("PDF library not loaded. Cannot download plan."); return; } const { jsPDF } = jspdf; const doc = new jsPDF(); let y = 20; const addTitle = (title) => { doc.setFontSize(18); doc.setTextColor(40, 40, 40); doc.text(title, 15, y); y += 10; }; const addDetail = (key, value) => { doc.setFontSize(11); doc.setTextColor(80, 80, 80); doc.text(`${key}:`, 20, y); doc.setTextColor(0, 0, 0); doc.text(value, 55, y); y += 7; }; doc.setFontSize(24); doc.text("Portfolio Layout Plan", 105, 15, { align: 'center' }); addTitle("Global Styles"); addDetail("Font", portfolioConfig.global.font); addDetail("Palette", `Primary: ${portfolioConfig.global.palette.primary}, Background: ${portfolioConfig.global.palette.bg}`); y += 5; addTitle("Hero Section"); addDetail("Layout", portfolioConfig.hero.layout); addDetail("Headline", portfolioConfig.hero.headline); addDetail("Subheading", portfolioConfig.hero.subheading); y += 5; addTitle("Projects Section"); addDetail("Title", portfolioConfig.projects.title); addDetail("Layout", portfolioConfig.projects.layout); addDetail("Count", String(portfolioConfig.projects.count)); y += 5; addTitle("Skills Section"); addDetail("Title", portfolioConfig.skills.title); addDetail("Display Style", portfolioConfig.skills.layout); doc.text("Skills List:", 20, y); y += 7; doc.setFontSize(10); const skillsText = doc.splitTextToSize(portfolioConfig.skills.list, 160); doc.text(skillsText, 25, y); y += skillsText.length * 5 + 5; addTitle("Contact Section"); addDetail("Title", portfolioConfig.contact.title); doc.text("Message:", 20, y); y += 7; doc.setFontSize(10); const contactText = doc.splitTextToSize(portfolioConfig.contact.text, 160); doc.text(contactText, 25, y); doc.save('Portfolio-Layout-Plan.pdf'); }); document.querySelector('.accordion-button[data-target="content-global"]').classList.add('active'); renderPreview(); });
Scroll to Top