CSV to VCard QR Code Generator: When Laziness Sparks Genius
Procrastination, But Make It Productive
CSV to VCard QR Code Generator: When Laziness Sparks Genius

Disclaimer: This isn’t a tutorial — because, let’s be honest, who has time for that? But hey, if I ever do make one, I’ll drop the link here.
Procrastination, But Make It Productive
Lately, I’ve been in this weird phase where if I face even the slightest inconvenience or repetitive task, my brain immediately goes, “Why not spend hours coding a solution instead of just doing it the easy way?” Productive procrastination at its finest.
So, here’s the story of how my refusal to do data entry for 70+ people led to me developing a whole CSV to VCard QR code generator. Buckle up, it’s a wild ride!
Tech Stack Alert: This little project was powered by the dynamic duo of Node.js and Express, sprinkled with some EJS magic for templating, stored safely in the cloud with MongoDB Atlas, and (fingers crossed) hosted on Render.
The Problem: A QR Code Conundrum
Picture this: My dad runs a company, and as part of a marketing campaign, he needed to generate QR codes for some VCard data. You know, those little .vcf files that, when opened, magically fill in your contact details and save them with one click? Here’s what they look like:

But here’s the kicker — those QR codes he generated required people to download the VCard file to their phone’s local storage before they could open it. Not exactly the smoothest user experience.
What we really needed was a QR code that would instantly launch the VCard on your phone, no downloading required. Ain’t nobody got time for extra steps!
To Google I Went
So, I did what any self-respecting developer would do — I Googled it. I found this nifty tool called GenQRCode, and it looked promising.

You could input your contact details and generate two kinds of QR codes:
- Static QR Code: Basically, a one-and-done deal. Once generated, it can’t be altered. Perfect for things that don’t change, like Wi-Fi passwords or our VCard data.
- Dynamic QR Code: These bad boys can be updated after creation. Useful for things like restaurant menus (seriously, does anyone actually enjoy scanning those?).
Naturally, I tried both. And guess what? The static QR code opened my address book right away — no downloads, no hassle. Meanwhile, the dynamic QR code required a download before I could even look at the contact info. Bingo! Static was the way to go.
But then, reality hit. We needed to generate over 70 QR codes. By tomorrow morning. And manually entering each person’s details? Yeah, hard pass.
The Lightbulb Moment
Now, I could either pay for a bulk QR code generator (ugh) or spend hours manually creating each one (double ugh). But then I thought, why not just build my own? I mean, why pay for a service when I can over-engineer a solution in the name of laziness?
So, I set a timer, fired up VSCode, and got to work.
Step 1: Parsing the CSV Data (AKA, The Boring Part)
First things first, I needed to parse the CSV data and upload it to a MongoDB Atlas database. Armed with Node.js and some trusty packages like csv-parser and fs, I managed to get all the data into the database.
Pro tip: Trim your CSV headers before uploading. I learned that the hard way after my database threw a fit.
mongoose.connect(mongooseString).then(() => console.log('Connected to MongoDB'))
.catch(err => console.log('MongoDB connection error:', err));
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
const results = []
fs.createReadStream(csvFile)
.pipe(csv({ mapHeaders: ({ header }) => header.trim() })) // Parse the CSV file
.on('data', (data) => {
// Push the parsed data to results
results.push({
firstName: data['firstName'.trim()],
lastName: data['lastName'.trim()],
email: data['email'.trim()],
cellno: data['cellno'.trim()],
address: data['address'.trim()],
website: data['website'.trim()],
title: data['title'.trim()],
org: data['org'.trim()],
city: data['city'.trim()],
state: data['state'.trim()],
country: data['country'.trim()],
pinCode: data['pinCode'.trim()]
});
})
.on('end', () => {
console.log(results);
// Insert parsed data into MongoDB
applicant.insertMany(results)
.then(() => {
console.log('CSV data successfully uploaded to MongoDB');
// Close the connection after upload
})
.catch(err => {
console.error('Error inserting data into MongoDB:', err);
});
});
app.listen(3000, () => {
console.log("Sever is now listening on port 3000");
})
Step 2: Making the Magic Happen
With the data safely tucked away in MongoDB, it was time to generate some VCards. I wrote a server script to fetch the data for all 70 members, convert it into VCard syntax, and store it in an array. Then, I looped over that array to convert the info into base64-encoded QR codes.
To keep things simple, I used EJS as my template engine. This made it a breeze to mix JavaScript logic directly into the HTML view.
Pro tip: Make sure the VCard boilerplate has absolutely no extra whitespace or auto-formatting — trust me, it won’t work, and you’ll spend 30 minutes pulling your hair out like I did. Lesson learned the hard way!
app.get('/',async(req,res)=>{
try{
const Users=await User.find();
const qrCodes=[];
for(const user of Users)
{
const vcard=createVCard(user);
// console.log(vcard);
try {
const qrCodeDataUrl = await QRCode.toDataURL(vcard);
qrCodes.push({ name: user.firstName + " " + user.lastName, org: user.org, qrCode: qrCodeDataUrl });
// console.log(qrCodeDataUrl);
} catch (error) {
console.error("Error generating QR code:", error);
}
}
res.render('index.ejs',{qrCodes});
}catch (error) {
console.error(error);
res.status(500).send('Internal Server Error');
}
})
app.get('/dev',(req,res)=>{
res.render('index.ejs')
})
app.listen(process.env.port,'0.0.0.0',()=>{
console.log("Sever is now listening on port "+process.env.port);
})
function createVCard(firstName,lastName,org,title,cellno,email,website,address,city,state,pinCode,country) {
return`BEGIN:VCARD
VERSION:3.0
N:${lastName};${firstName}
FN:${firstName} ${lastName}
ORG:${org || 'N/A'}
TITLE:${title || 'N/A'}
TEL;TYPE=CELL:${cellno}
EMAIL:${email}
URL:${website || ''}
ADR;TYPE=WORK:;;${address};${city};${state};${pinCode};${country}
END:VCARD`;
}
Step 3: Show Me the QR Codes!
Next up, I needed a way to display these QR codes. I threw together a list view table with three columns: name, company, and the QR code itself. Since the QR codes were base64-encoded, I added a little script to decode and display them as images.
And just like that, scanning the QR code on my Android phone popped open my address book with all the contact info filled in. Boom!
Step 4: Download All the Things
Now, I couldn’t just stop there. I wanted the ability to download each QR code individually, or all of them at once. Using multer and fs, I added download buttons for each QR code, and a master button that zipped up all the codes for one-click downloading.
Final Thoughts: Mission Accomplished!
In the end, my refusal to do manual data entry led to a fully functional CSV to VCard QR code generator. What was supposed to be a tedious task turned into a fun little coding adventure. And the best part? It only took about an hour and fifty minutes to build.
So, the next time you’re faced with a boring, repetitive task, ask yourself: “Can I code my way out of this?” The answer is probably yes. And if it’s not, well, at least you’ll have some fun trying!
And hey, if you’re the curious type or just want to snag some code, check out the repo here and give the tool a whirl. **Here’s the website that started it all — just a heads up, it’s on Render’s free tier, so it might take a nap when you try to visit.** Happy QR coding!
메타데이터
- post_id
- efcfe94734e1
- slug
- csv-to-vcard-qr-code-generator-when-laziness-sparks-genius-efcfe94734e1
- url
- https://medium.com/@atulreny911/csv-to-vcard-qr-code-generator-when-laziness-sparks-genius-efcfe94734e1
- canonical_url
- https://medium.com/@atulreny911/csv-to-vcard-qr-code-generator-when-laziness-sparks-genius-efcfe94734e1
- author_url
- https://medium.com/@atulreny911
- status
- ok
- fetched_at
- 2026-07-13 06:23:13