Celebrating Your Wins: What Made Your Week Unforgettable
Source: Dev.to
As developers, we often focus on what’s broken, what’s next, or what we haven’t shipped yet. But growth happens when we pause and reflect on what did work — the small bugs we fixed, the feature we shipped, or the new concept we finally understood.
In this tutorial, we’ll build a simple “Weekly Wins Tracker” using Node.js and Express, with data stored in a JSON file. It’s beginner‑friendly, code‑heavy, and perfect for celebrating your progress — one week at a time.
By the end, you’ll have a working web app where you can:
- Add your weekly win
- View all wins
- Celebrate your progress with emoji confetti 🎉
Let’s get started!
Step 1: Set Up Your Project
Create a new directory and initialize a Node.js project:
mkdir weekly-wins-tracker
cd weekly-wins-tracker
npm init -y
Install Express:
npm install express
Install nodemon for auto‑restarting during development (optional but recommended):
npm install --save-dev nodemon
Update your package.json scripts:
{
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js"
}
}
Step 2: Create the Server
Create server.js:
const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();
const PORT = 3000;
// Middleware to parse JSON and serve static files
app.use(express.json());
app.use(express.static('public'));
We’re using:
express.json()to parse incoming JSONexpress.static('public')to serve HTML, CSS, and JS files
Step 3: Set Up Data Storage
We’ll store wins in a JSON file called wins.json.
Create wins.json in your project root:
[]
Add helper functions to read and write wins:
const WINS_FILE = path.join(__dirname, 'wins.json');
// Read wins from file
function readWins() {
const data = fs.readFileSync(WINS_FILE);
return JSON.parse(data);
}
// Write wins to file
function writeWins(wins) {
fs.writeFileSync(WINS_FILE, JSON.stringify(wins, null, 2));
}
Step 4: Build the API Endpoints
We’ll create three routes:
GET /wins– get all winsPOST /wins– add a new winGET /– serve the frontend
Add the routes:
// Get all wins
app.get('/wins', (req, res) => {
try {
const wins = readWins();
res.json(wins);
} catch (err) {
res.status(500).json({ error: 'Failed to read wins' });
}
});
// Add a new win
app.post('/wins', (req, res) => {
const { text } = req.body;
if (!text || text.trim() === '') {
return res.status(400).json({ error: 'Win text is required' });
}
const newWin = {
id: Date.now().toString(),
text: text.trim(),
date: new Date().toISOString().split('T')[0]
};
const wins = readWins();
wins.push(newWin);
writeWins(wins);
res.status(201).json(newWin);
});
Don’t forget to start the server at the end of server.js:
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
Step 5: Create the Frontend
Create a public folder and add index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Weekly Wins Tracker</title>
<style>
body {
font-family: 'Segoe UI', sans-serif;
max-width: 600px;
margin: 40px auto;
padding: 20px;
background: #f9f9ff;
color: #333;
}
h1 { color: #4a4a98; text-align: center; }
input, button {
padding: 10px;
margin: 10px 0;
width: 100%;
box-sizing: border-box;
}
button {
background: #4a4a98;
color: white;
border: none;
cursor: pointer;
}
ul {
list-style: none;
padding: 0;
}
li {
background: white;
margin: 8px 0;
padding: 12px;
border-radius: 6px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.confetti {
font-size: 1.5em;
margin-right: 8px;
}
</style>
</head>
<body>
<h1>🎉 Celebrate Your Wins</h1>
<input type="text" id="winInput" placeholder="What did you achieve this week?" />
<button onclick="addWin()">Add Win</button>
<ul id="winsList"></ul>
<script>
// Load wins on page load
window.onload = loadWins;
async function loadWins() {
const res = await fetch('/wins');
const wins = await res.json();
const list = document.getElementById('winsList');
list.innerHTML = '';
wins.forEach(win => {
const li = document.createElement('li');
li.innerHTML = `🎊${win.text} (${win.date})`;
list.appendChild(li);
});
}
async function addWin() {
const input = document.getElementById('winInput');
const text = input.value.trim();
if (!text) return;
const res = await fetch('/wins', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text })
});
if (res.ok) {
input.value = '';
loadWins();
} else {
const err = await res.json();
alert(err.error);
}
}
</script>
</body>
</html>
Now run the app:
npm run dev # or npm start
Open http://localhost:3000 in your browser, add a few wins, and watch the list grow with confetti! 🎉