Build a Portfolio Builder App: Hands-On Tutorial
This project guides you through creating a simple Portfolio Builder using HTML, CSS, and JavaScript in VS Code. You'll learn to build an interactive web app that lets users add projects, skills, and generate a shareable portfolio page—all from scratch. Perfect for beginners wanting to practice DOM manipulation and local storage.
Prerequisites What tech stack did you use (HTML/CSS/JS, React, etc.)? Reply with that, plus a 1-sentence description of what your app does (e.g., "Adds project cards via form and saves to localStorage"). Then we'll craft the exact Prerequisites section together. Project Setup Follow these steps to get the Portfolio Builder running locally in VS Code.
-
Clone or download the repository
Open terminal in VS Code (Ctrl+``). Run:
Or download ZIP from GitHub and extract. -
No dependencies to install
Uses only vanilla HTML, CSS, and JavaScript. -
Run the project
- Install Live Server extension in VS Code.
- Right-click
index.html→ "Open with Live Server". - View at
http://localhost:5500.
Start with a clean HTML file that sets up the form and preview iframe.
<title>Portfolio Builder</title>Reply "Continue" and we'll add Step 2: Build the Input Form (name, role, about, skills, projects, contact fields from your code). Then Step 3 for CSS, Step 4 for JavaScript (generate + download logic). We'll extract your actual code snippets into each step!
Step 2: Build the Input Form Add all the form fields inside the .builder-form div to collect user data for the portfolio.
Your Name
Your Role
About You
<textarea id="about" rows="4" placeholder="Write a short bio about yourself..."></textarea> Enter comma-separated skills Format: title|description|link (one per line) <textarea id="projects" rows="6" placeholder="E-commerce App|Built with React and Node|https://example.com"></textarea> EmailGitHub URL
LinkedIn URL
Generate Portfolio Download HTML
.builder-form { flex: 1; padding: 20px; border: 1px solid #ddd; border-radius: 8px; background: #f9f9f9; }
.preview { flex: 1; border: none; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); min-height: 600px; }
label { display: block; margin: 10px 0 5px; font-weight: bold; } input, textarea { width: 100%; padding: 10px; border: 1px solid #ccc; border-radius: 4px; } button { background: #007bff; color: white; padding: 12px 24px; border: none; border-radius: 4px; cursor: pointer; margin: 10px 5px 0 0; } button:hover { background: #0056b3; } Step 4: Add JavaScript Functionality Create script.js to handle form data, generate portfolio HTML, display in iframe, and enable download. // Get form elements const generateBtn = document.getElementById('generate-btn'); const downloadBtn = document.getElementById('download-btn'); const resultIframe = document.getElementById('result');
// Generate portfolio on button click generateBtn.addEventListener('click', () => { const name = document.getElementById('name').value; const role = document.getElementById('role').value; const about = document.getElementById('about').value; const skillsInput = document.getElementById('skills').value; const projectsInput = document.getElementById('projects').value; const email = document.getElementById('email').value; const github = document.getElementById('github').value; const linkedin = document.getElementById('linkedin').value;
// Parse skills and projects const skills = skillsInput.split(',').map(s => s.trim()).filter(s => s); const projects = projectsInput.split('\n').map(line => { const [title, desc, link] = line.split('|').map(p => p.trim()); return { title, desc, link }; }).filter(p => p.title);
// Generate portfolio HTML
const portfolioHTML = <!DOCTYPE html> <html> <head> <title>${name} - Portfolio</title> <style> body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; } header { text-align: center; background: #007bff; color: white; padding: 40px 20px; } section { margin: 30px 0; } h2 { color: #333; border-bottom: 2px solid #007bff; padding-bottom: 10px; } ul { list-style: none; padding: 0; } li { background: #f8f9fa; margin: 10px 0; padding: 15px; border-radius: 5px; } a { color: #007bff; text-decoration: none; } .contact { display: flex; gap: 20px; justify-content: center; } </style> </head> <body> <header> <h1>${name}</h1> <h2>${role}</h2> </header> <section> <h2>About</h2> <p>${about}</p> </section> <section> <h2>Skills</h2> <ul>${skills.map(skill =>
).join('')}</ul> </section> <section> <h2>Projects</h2> ${projects.map(p => ${p.desc}
View Project
).join('')} </section> <section> <h2>Contact</h2> <div class="contact"> ${email ? ${email}: ''} ${github ?GitHub: ''} ${linkedin ?LinkedIn: ''} </div> </section> </body> </html>;
// Load into iframe const iframeDoc = resultIframe.contentDocument || resultIframe.contentWindow.document; iframeDoc.open(); iframeDoc.write(portfolioHTML); iframeDoc.close(); });
// Download HTML file downloadBtn.addEventListener('click', () => { const iframeDoc = resultIframe.contentDocument || resultIframe.contentWindow.document; const htmlContent = iframeDoc.documentElement.outerHTML; const blob = new Blob([htmlContent], { type: 'text/html' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'my-portfolio.html'; a.click(); URL.revokeObjectURL(url); });
Usage & Demo Fill out the form with your details (skills as comma-separated, projects as "title|desc|link" per line).
Click Generate Portfolio to see live preview in the iframe.
Click Download HTML to save your portfolio as a standalone .html file—open anywhere!