DEV Community

Orbit Websites
Orbit Websites

Posted on

Celebrating Your Wins: What Made Your Week Unforgettable

Celebrating Your Wins: What Made Your Week Unforgettable

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
Enter fullscreen mode Exit fullscreen mode

Install Express:

npm install express
Enter fullscreen mode Exit fullscreen mode

Install nodemon for auto-restarting during development (optional but recommended):

npm install --save-dev nodemon
Enter fullscreen mode Exit fullscreen mode

Update your package.json scripts:

"scripts": {
  "start": "node server.js",
  "dev": "nodemon server.js"
}
Enter fullscreen mode Exit fullscreen mode

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'));
Enter fullscreen mode Exit fullscreen mode

We’re using:

  • express.json() to parse incoming JSON
  • express.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:

[]
Enter fullscreen mode Exit fullscreen mode

Now, 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));
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Build the API Endpoints

Let’s create three routes:

  • GET /wins – get all wins
  • POST /wins – add a new win
  • GET / – 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);
});
Enter fullscreen mode Exit fullscreen mode

Step 5: Create the Frontend

Create a public folder and add index.html:


html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <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="I shipped my first Express app!" />
  <button onclick="addWin()">Add Win</button>
  <ul id="winsList"></ul>

  <script>
    // Load wins on page load
    window.onload = loadWins

---

☕ **Playful**
Enter fullscreen mode Exit fullscreen mode

Top comments (0)