I Built an “Ethical” GitHub Streak Guardian (And How I Survived API Rate Limits)

We’ve all been there. You’re deep in the zone, debugging a race condition or refactoring a messy component. You code for 8 hours straight. You close your laptop, exhausted but proud.

The next morning, you check your GitHub profile and see… a gray sq…


This content originally appeared on DEV Community and was authored by Devanshu P.

We’ve all been there. You’re deep in the zone, debugging a race condition or refactoring a messy component. You code for 8 hours straight. You close your laptop, exhausted but proud.

The next morning, you check your GitHub profile and see... a gray square.

You forgot to push. Your 100-day streak is gone. 📉

I built DailyDiff to solve this. But I didn't want to build just another "fake commit bot" that spams update readme 50 times a day. I wanted to build a productivity companion that respects the spirit of open source while protecting your consistency.

Here is a deep dive into how I built a full-stack, timezone-aware automation tool using React, Node.js, Supabase, and the GitHub GraphQL API.

💡 The Core Concept: Ethical Automation

Most streak savers are simple scripts that push empty commits. DailyDiff is different. It offers Content Strategies:

  1. Learning Logs: It can append what you learned that day to a repo.
  2. Micro-Tasks: Stuck in "coder's block"? It suggests real tasks (like "Refactor variable names" or "Add JSDoc") to unblock you.
  3. Timezone Intelligence: It knows your day isn't over until it's midnight in your city, not UTC.

🛠 The Tech Stack

I chose a distributed architecture to keep the frontend fast and the backend persistent.

  • Frontend: React (Vite) + Tailwind CSS (deployed on Vercel).
  • Backend: Node.js + Express (deployed on Render).
  • Database: Supabase (PostgreSQL) for storing user schedules and OAuth tokens.
  • Automation: node-cron for background job scheduling.
  • Auth: GitHub OAuth 2.0.

🧠 Technical Deep Dive: The "Minor" Details That Matter

Building a CRUD app is easy. Building a system that runs reliably in the background on free-tier infrastructure is where it gets interesting. Here are the three biggest engineering challenges I solved.

1. The "Sleeping Server" Problem

I deployed the backend to Render's Free Tier. It’s great, but it has a catch: it spins down after 15 minutes of inactivity.

If my server is asleep, the Cron job responsible for checking commit schedules (cron.schedule('* * * * *')) dies.

The Solution: The Heartbeat Route
I added a lightweight health-check endpoint in Express:

// server/index.js
app.get('/', (req, res) => {
  res.status(200).send('✅ DailyDiff Backend is Active');
});

Then, I set up an external monitor (using cron-job.org) to ping this route every 14 minutes. This keeps the Render instance "warm" 24/7 without costing a dime, ensuring user automations never miss a beat.

2. Solving GitHub API Rate Limits (The Hybrid Cache)

DailyDiff visualizes your contribution history using a beautiful heatmap. To render this, I fetch data using GitHub's GraphQL API.

The problem? fetching a year's worth of contribution data is expensive. During development (thanks to React Strict Mode double-invoking useEffect), I hit GitHub's 5,000 req/hour limit constantly.

The Solution: A Hybrid Caching Strategy

I implemented a two-layer cache to protect my API quota:

  1. Layer 1: Client-Side (LocalStorage)
    Before the frontend even talks to the server, it checks localStorage. If valid data exists (less than 1 hour old), it renders instantly. 0ms latency, 0 API calls.

  2. Layer 2: Server-Side (Disk Cache)
    If the client cache misses, the request hits the server. The server checks a local JSON file (cache_contributions.json). Even though Render has an ephemeral filesystem, this disk cache survives brief restarts and prevents the "thundering herd" problem if multiple clients connect simultaneously.

// Code snippet from my caching logic
const cachedRaw = localStorage.getItem(CACHE_KEY);
if (cachedRaw) {
    const { timestamp, data } = JSON.parse(cachedRaw);
    const age = Date.now() - timestamp;
    if (age < CACHE_DURATION) {
        return data; // Return early!
    }
}

3. Timezone-Aware Cron Jobs

Servers run on UTC. Users do not.
If a user in India (IST) sets a reminder for 11:00 PM, but my server is in Oregon (UTC-7), a standard cron job fails.

I couldn't just store 23:00 in the database. I had to store the user's Timezone (Asia/Kolkata) alongside the time.

In the backend cron loop, I don't check if ServerTime == UserTime. instead, I dynamically convert the server's now() into the user's local time before comparing:

// Inside the Cron Loop
const userTimeString = new Date().toLocaleTimeString('en-US', {
  timeZone: job.timezone, // e.g., 'Asia/Kolkata'
  hour: '2-digit', 
  minute: '2-digit',
  hour12: false
});

if (userTimeString === job.schedule_time) {
   // Fire the commit!
}

This ensures that 8:00 PM feels like 8:00 PM, no matter where the server is located.

🎨 UI/UX: The "GitHub Dark Mode" Aesthetic

I wanted the app to feel native to the developer ecosystem. I utilized Tailwind CSS to mirror GitHub's specific dark mode color palette (#0d1117 for background, #39d353 for success states).

I also implemented a React Portal for the tooltips on the activity graph. Because the graph is in a container with overflow-x: auto (for scrolling), a standard absolute tooltip would get clipped. Portaling it to document.body allows it to float freely above the UI.

🚀 Deployment & Security

Deploying a separated frontend and backend required strict CORS and Cookie configuration.

Since the frontend (vercel.app) and backend (onrender.com) are on different domains, I had to set the session cookies to SameSite: none and Secure: true.

app.use(cookieSession({
  name: 'session',
  keys: [process.env.SESSION_SECRET],
  // Required for cross-site cookies between Vercel and Render
  sameSite: process.env.NODE_ENV === 'production' ? 'none' : 'lax',
  secure: process.env.NODE_ENV === 'production', 
  httpOnly: true
}));

🔮 What's Next?

DailyDiff is currently in v1. I'm planning to add:

  • AI-Generated Commit Content: Using OpenAI to read the user's actual code changes and suggest commit messages.
  • Team Leaderboards: Gamifying the streak experience.

🔗 Links

This project is fully open-source. I’d love for you to check out the code, fork it, or give it a star if you find it useful!

Thanks for reading! Let me know in the comments—have you ever lost a 100+ day streak? 😅


This content originally appeared on DEV Community and was authored by Devanshu P.


Print Share Comment Cite Upload Translate Updates
APA

Devanshu P. | Sciencx (2025-11-22T21:01:17+00:00) I Built an “Ethical” GitHub Streak Guardian (And How I Survived API Rate Limits). Retrieved from https://www.scien.cx/2025/11/22/i-built-an-ethical-github-streak-guardian-and-how-i-survived-api-rate-limits/

MLA
" » I Built an “Ethical” GitHub Streak Guardian (And How I Survived API Rate Limits)." Devanshu P. | Sciencx - Saturday November 22, 2025, https://www.scien.cx/2025/11/22/i-built-an-ethical-github-streak-guardian-and-how-i-survived-api-rate-limits/
HARVARD
Devanshu P. | Sciencx Saturday November 22, 2025 » I Built an “Ethical” GitHub Streak Guardian (And How I Survived API Rate Limits)., viewed ,<https://www.scien.cx/2025/11/22/i-built-an-ethical-github-streak-guardian-and-how-i-survived-api-rate-limits/>
VANCOUVER
Devanshu P. | Sciencx - » I Built an “Ethical” GitHub Streak Guardian (And How I Survived API Rate Limits). [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/11/22/i-built-an-ethical-github-streak-guardian-and-how-i-survived-api-rate-limits/
CHICAGO
" » I Built an “Ethical” GitHub Streak Guardian (And How I Survived API Rate Limits)." Devanshu P. | Sciencx - Accessed . https://www.scien.cx/2025/11/22/i-built-an-ethical-github-streak-guardian-and-how-i-survived-api-rate-limits/
IEEE
" » I Built an “Ethical” GitHub Streak Guardian (And How I Survived API Rate Limits)." Devanshu P. | Sciencx [Online]. Available: https://www.scien.cx/2025/11/22/i-built-an-ethical-github-streak-guardian-and-how-i-survived-api-rate-limits/. [Accessed: ]
rf:citation
» I Built an “Ethical” GitHub Streak Guardian (And How I Survived API Rate Limits) | Devanshu P. | Sciencx | https://www.scien.cx/2025/11/22/i-built-an-ethical-github-streak-guardian-and-how-i-survived-api-rate-limits/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.