A simple, responsive personal portfolio with sections for home, about, projects, skills, and a resume area that includes:
- A Resume download button (linking to a PDF you provide)
- An optional Resume upload form with client-side checks (PDF only, up to 10 MB)
- Replace the placeholder content in
index.htmlwith your details. - Put your resume PDF at
assets/resume/YourName-Resume.pdfor update the download link inindex.html. - Open
index.htmlin a browser (or serve locally for best results).
You can use a simple static server, for example:
npx serve .
The upload form performs client-side validation for file type and size. To actually receive uploaded files, you need a backend endpoint. Configure it in index.html:
<script>
window.SITE_CONFIG = {
uploadEndpoint: null // e.g. 'https://your-api.example.com/upload'
};
</script>When uploadEndpoint is set, the form POSTs a FormData with field name resume to that URL.
Below is a minimal example using Express and Multer to accept the PDF. Save as server.js and run with Node. Ensure you run npm init -y && npm i express multer cors first.
const express = require('express');
const multer = require('multer');
const cors = require('cors');
const app = express();
app.use(cors());
const upload = multer({
limits: { fileSize: 10 * 1024 * 1024 }, // 10 MB
fileFilter: (req, file, cb) => {
if (file.mimetype === 'application/pdf') cb(null, true);
else cb(new Error('Only PDF files allowed'));
}
});
app.post('/upload', upload.single('resume'), (req, res) => {
// req.file contains the uploaded PDF (buffer or path depending on storage)
// Save to disk/cloud, then respond
res.json({ ok: true });
});
app.use((err, req, res, next) => {
res.status(400).json({ ok: false, error: err.message });
});
app.listen(3000, () => console.log('Upload server on http://localhost:3000'));Set uploadEndpoint to http://localhost:3000/upload while testing locally.
- Text and sections: edit
index.html. - Styles: edit
assets/css/styles.css. - Behavior: edit
assets/js/main.js. - Resume download path: update the
hrefin the Resume/Download button.
- The upload form uses clear labels, live status text, and size/type checks.
- Without a backend, the upload form will validate and show status but will not transmit files.