DevPulse banner

DevPulse

3 devlogs
12h 29m 22s

DevPulse is a high-performance, self-hosted, real-time developer dashboard built in C++ and Crow that showcases coding activity, GitHub commits, and Hackatime data. It serves as a live, embeddable "dev card" aimed at highlighting technical ambitio…

DevPulse is a high-performance, self-hosted, real-time developer dashboard built in C++ and Crow that showcases coding activity, GitHub commits, and Hackatime data. It serves as a live, embeddable “dev card” aimed at highlighting technical ambition for the Hack Club community through WebSocket updates and OAuth integration.

This project uses AI

ChatGPT for debugging,README and help with css

Demo Repository

Loading README...

panayiotis.savva8

DevPulse: DevLog #3 – Ship Day

Today was the day DevPulse went live. After two devlogs of architecture and backend work, this session was about closing the loop — wiring the frontend, surviving some brutal debugging, and actually deploying to production.

The Dashboard Comes Alive

The frontend was the last big piece. I built the full dashboard in vanilla JS and HTML — stat cards with live counters, a real-time activity feed, language bars, share/embed section, and settings. No framework, just clean DOM manipulation talking directly to the C++ backend over WebSockets.

The design follows the same philosophy as the backend: minimal dependencies, maximum control.

The Bug That Broke Everything

This is the one I’ll remember.

I opened dashboard.js in my editor, made some changes, and the app broke completely. The dashboard was permanently stuck on “Loading…” — nothing rendered, no errors I could find at first.

After digging into the network tab I found the real culprit: the file was 0 bytes. My editor had crashed mid-save and truncated the entire file to nothing. Docker had then faithfully copied the empty file into the container, so loadMe was never defined — hence the ReferenceError: Can't find variable: loadMe in the console.

On top of that, the first time I logged in via GitHub OAuth, the JS files were being fetched by GitHub’s servers (140.82.121.5), not my browser — which meant the browser never got them at all. The inline bootstrap script fired before the files loaded and called a function that didn’t exist yet.

The fix was twofold: restore the file, and move the bootstrap IIFE into dashboard.js itself so it only runs once the file is actually parsed.

Landing Page Redesign

The original landing page was functional but generic. I rebuilt it from scratch:

  • Grid background with an indigo glow orb
  • Space Mono for all numbers and code elements, DM Sans for body copy
  • Bento grid feature layout
  • Terminal mockup showing the webhook flow in real time
  • Live demo profile preview with animated commit ticker
  • Scroll reveal animations on every section

The goal was for it to feel like a real product, not a side project.

Demo Account

Since reviewers can’t sign in with their own GitHub to see the dashboard, I hardcoded a demo account (hackclub-demo) that seeds itself on every server startup via seedDemoAccount() in main.cpp. It has realistic stats, language breakdown, and activity feed entries — all inserted directly via SQLite at boot. No CLI, no manual steps, survives every deploy.

Deployment

Deployed to Fly.io with a persistent SQLite volume. The whole stack — C++ binary, static files, SQLite DB — runs in a single 512MB container. Cold starts are fast because there’s no runtime to boot, just an executable.

Fly config gotcha: I had both [http_service] and [[services]] defined, which caused duplicate port binding. Removed the [[services]] block and the health check was pointed at /health which didn’t exist — changed it to /.

What’s Live

0
panayiotis.savva8

DevPulse: DevLog #2 – Wiring the C++ Engine
Today was about integration. I moved from standalone service headers to a fully functional main.cpp.

  • Hardened Headers: I implemented addSecurityHeaders() to inject CSP (Content Security Policy), HSTS, and X-XSS protection into every response.
  • The Session Handshake: I built a custom session extractor. It doesn’t just read a cookie; it validates the token length and uses a secure safeCompare to prevent timing attacks.
  • CSRF Protection: Implemented a double-submit cookie pattern for state-changing requests, ensuring that the dashboard isn’t vulnerable to cross-site exploits.
  • The Stats & Badge Engine
    One of the coolest parts of today was building the SVG Badge Generator.
    Instead of just serving JSON, I wrote a C++ helper that dynamically generates SVG code. This allows users to embed their “DevPulse” directly into their GitHub READMEs.
  • JSON Composition: I wrote buildProfileJson, which aggregates data from the user table, the stats cache, and the activity feed into a single, optimized response. This minimizes database round-trips and keeps the “Pulse” fast.
  • Performance & Rate Limiting
  • Privacy-First Rate Limiting: I implemented an IP-based rate limiter, but with a twist: I hash the user’s IP address before storing it to avoid keeping PII (Personally Identifiable Information) in the memory/DB logs.
  • Environment Management: Wrote a custom .env loader to handle secrets like GitHub Client IDs without hardcoding them into the binary.
  • The C++ Advantage
    The more I build, the more I see why C++ is the right choice for this. The way the server handles WebSockets and background threads for stats refreshing is incredibly lightweight compared to a typical Node.js overhead.
    Current Stack Progress:
  • Security Middleware (Headers/CSRF)
  • Session & Auth Logic
  • Dynamic SVG Generation
  • SQLite Integration
    Next up: Building the Frontend of DevPulse
Attachment
Attachment
Attachment
0
panayiotis.savva8

DevPulse: DevLog #1 – Core Architecture & Security Hardening
Today’s focus was on laying the groundwork for the backend.

Security & Input Handling (security.h)
I started by implementing a dedicated security header. Since C++ gives you direct memory access, I wanted to address the OWASP Top 10 from the first line of code.

  • Sanitization: Implemented manual input filtering to prevent SQL injection and XSS.
  • CSRF/Headers: Started logic for secure cookie handling and security headers.
  • Database Schema & User Logic
    I finalized the SQLite schema. I decided to decouple the users table from a stats_cache table. This allows the background worker to update GitHub activity (commits, languages, streaks) without locking the primary user record. The user_service.h now handles the CRUD operations for user profiles and maps DB rows to C++ structs.
  • GitHub Integration (github_service.h)
    This module handles the OAuth 2.0 handshake. I’m using the CPR (C++ Requests) library to interface with GitHub’s REST API.
  • OAuth Flow: Handled the exchange of the temporary code for an access token.
  • Data Fetching: Wrote the logic to fetch user JSON data. The main challenge here is safely parsing nested JSON fields (using nlohmann/json) into local database types while handling potential API rate limits or malformed responses.
  • Real-time State (ws_manager.h)
    To achieve the “Pulse” effect, I built a WebSocket connection manager. It tracks active client connections and provides an interface for the backend to “push” updates to the frontend. This means when a GitHub webhook or a background refresh triggers a change in stats, the dashboard can update instantly without a page reload.
  • Next Steps:
    The skeleton is functional. Tomorrow, I’ll be working on the background refresh thread—it needs to cycle through the database and update stats for all users every 10–15 minutes without blocking the main event loop.
Attachment
Attachment
Attachment
0