DEV Community

Sarvar Nadaf
Sarvar Nadaf

Posted on

I Added Terminal Charts to My Dev.to CLI. Here's What My Data Looks Like.

TL;DR: pip install devpub==0.2.1devpub stats --graph → color-gradient bar charts, sparklines, trend arrows, and multi-period breakdowns for your Dev.to analytics. Zero new dependencies. GitHub repo / PR #10.


I check my Dev.to stats obsessively. Page views, reactions, which articles are climbing, which ones flatlined. But switching to the browser, clicking through dashboards, waiting for pages to load... it breaks my flow every single time.

So I built charts directly into devpub.

pip install devpub==0.2.1
devpub stats --graph
Enter fullscreen mode Exit fullscreen mode

That one command now gives me this:

  Views (last 30 days)  ↘ -18%

     871 ┤                 █
         │                ██ ▂██     █▂
     653 ┤                ██ ███▇ ▆  █▆
         │               ▃██▅████▁█▆ ███
     435 ┤·▃····▁········███████████·███▃ ← avg (451)
         │▄█    █▆▁    ▂ ███████████▄████
     217 ┤████▇██████▅███████████████████
         │███████████████████████████████
         └───────────────────────────────
          Jul 21      Aug 05      Aug 20

  trend: ▃▄▃▃▂▃▄▃▃▃▃▂▃▃▃▄▆█▄▆▆▇▆▄▆▄▃▇▆▅▄

  Total: 14.0K │ Avg: 451/day │ Peak: 871 ▲ Aug 07

  Period Breakdown

   7 days: ▅▆▅▄█▆▆▄                         ↗ +9%   Total: 3.8K
  14 days: █▄▆▆▇▆▄▆▄▃▇▆▅▄                  ↘ -18%   Total: 8.5K
  21 days: ▃▂▃▃▃▄▆█▄▆▆▇▆▄▆▄▃▇▆▅▄           ↘ -18%   Total: 10.9K
  30 days: ▄▃▃▂▃▄▃▃▃▃▂▃▃▃▄▆█▄▆▆▇▆▄▆▄▃▇▆▅▄  ↘ -18%   Total: 13.7K
Enter fullscreen mode Exit fullscreen mode

That's real data from my account. 257K total views, 24K followers, rendered in 0.3 seconds. No browser needed.


Table of Contents


What changed in v0.2

Version 0.1 had --graph as a flag that did nothing. I shipped the flag first, then built the feature. Classic.

Version 0.2.1 makes it real:

Feature What it does
Color gradient bars Bars fade blue (low) → cyan → green → gold (peak)
Sparkline one-liner Compact 30-character trend below the chart
Trend indicator Arrow + percentage comparing recent vs previous period
Average line Dotted line across chart showing mean, with label
Peak marker Gold highlight with date in the summary
Box-drawing axes Clean tick marks using Unicode characters
12-row height More vertical resolution than before
Multi-period breakdown 7d, 14d, 21d, 30d sparklines with individual trends
Period flag -p 7d, -p 90d, -p 3m for any timeframe

All of this renders in the terminal. No image generation. No external services. No new dependencies.


The color gradient system

Most terminal charts use one color. Cyan. Green. Whatever. Every bar looks the same regardless of value.

I wanted the peak to visually pop. So bars shift color based on their height relative to the maximum:

Value range Color Purpose
0–25% Blue Low days, weekends
25–50% Cyan Below average
50–75% Green Good days
75–95% Lime Great days
95–100% Gold Peak day

The implementation is simple. One function that maps a 0–1 ratio to an RGB color string:

def _value_to_color(ratio: float) -> str:
    if ratio < 0.25:
        g = int(100 + ratio * 4 * 80)
        return f"rgb(50,{g},220)"
    elif ratio < 0.50:
        r = int((ratio - 0.25) * 4 * 50)
        return f"rgb({r},200,200)"
    elif ratio < 0.75:
        b = int(200 - (ratio - 0.50) * 4 * 150)
        return f"rgb(0,210,{b})"
    elif ratio < 0.95:
        r = int((ratio - 0.75) * 5 * 200)
        return f"rgb({r},220,50)"
    else:
        return "rgb(255,200,0)"
Enter fullscreen mode Exit fullscreen mode

Rich handles the RGB rendering. Works in any modern terminal that supports 24-bit color (iTerm2, Windows Terminal, Ghostty, Kitty, Alacritty, WezTerm).


Multi-period sparklines

This is my favorite addition. After the main chart, you get a breakdown:

  Period Breakdown

   7 days: ▅▆▅▄█▆▆▄                         ↗ +9%   Total: 3.8K
  14 days: █▄▆▆▇▆▄▆▄▃▇▆▅▄                  ↘ -18%   Total: 8.5K
  21 days: ▃▂▃▃▃▄▆█▄▆▆▇▆▄▆▄▃▇▆▅▄           ↘ -18%   Total: 10.9K
  30 days: ▄▃▃▂▃▄▃▃▃▃▂▃▃▃▄▆█▄▆▆▇▆▄▆▄▃▇▆▅▄  ↘ -18%   Total: 13.7K
Enter fullscreen mode Exit fullscreen mode

Why this matters: the 30-day trend might be down, but the 7-day trend tells you if you're recovering. In my case, overall traffic dropped 18% (I didn't publish for a week), but the last 7 days show +9% (new articles bringing it back).

Without multi-period comparison, you'd just see "down 18%" and feel bad. With it, you see the recovery in progress.

The sparkline characters (▁▂▃▄▅▆▇█) give you 8 levels of resolution per character. A 30-character sparkline shows 30 days of data in a single line. Your eye can instantly spot patterns: weekday/weekend cycles, post-publish spikes, gradual decay.


The average line

One detail that took surprisingly long to get right: the dotted average line.

     435 ┤·▃····▁········███████████·███▃ ← avg (451)
Enter fullscreen mode Exit fullscreen mode

It runs across the chart at the mean value height. Bars above it are above average. Bars below are below. The label tells you the exact number.

Why it matters: without it, you're guessing whether a day was "good" or "bad." The line gives you an instant reference. Tuesday's 500 views looks small next to Monday's 871 peak, but the average line shows it's actually above average.


How I built it (zero new dependencies)

The entire chart system uses:

  • Rich (already a dependency) for colored output and console.print
  • Python stdlib for math, datetime, and string operations
  • Unicode block characters (▁▂▃▄▅▆▇█) for sub-character resolution

No matplotlib. No plotext. No termgraph. No asciichart. I looked at all of them. They either add heavy dependencies, produce output that doesn't integrate with Rich's markup system, or require complex setup.

Pure Python + Rich gives me:

  • Full control over every character
  • Rich markup ([bold], [rgb(r,g,b)]) works inline
  • Zero import time penalty
  • 41 tests covering all helper functions
  • Works on Python 3.10+

The whole implementation is ~200 lines in one file. No architecture astronautics needed.

Full implementation: PR #10 — 41 tests, lint clean, handles edge cases (zero data, single day, large accounts with 90+ days).


Try it yourself

pip install devpub==0.2.1
Enter fullscreen mode Exit fullscreen mode

Set your Dev.to API key (get it at dev.to/settings/extensions):

export DEVPUB_API_KEY=your_key_here
Enter fullscreen mode Exit fullscreen mode

Then:

devpub stats --graph              # 30-day chart (default)
devpub stats --graph -p 7d        # Last 7 days
devpub stats --graph -p 90d       # Last 90 days (auto-downsamples)
devpub stats --graph -p 2w        # Last 2 weeks
Enter fullscreen mode Exit fullscreen mode

Star the repo if terminal analytics resonates with you.


What's next

v0.3 will add the Concepts API integration. Dev.to has an ML-powered topic classification system that most people don't know exists. It classifies articles into semantic concepts with daily metrics. devpub concepts will let you discover trending topics, find gaps in coverage, and see which concepts your articles fit into.

But that's next week. For now, try devpub stats --graph and tell me what your chart looks like.


What's your Dev.to stats workflow right now? Browser dashboard? Ignoring it entirely? Something else? Drop it in the comments — I'm curious how other writers track their content performance.


This is part 2 of the "Building DevPub in Public" series. Part 1: Introducing DevPub


Built by Sarvar Nadaf | Cloud Architect | Cloud, AI Infrastructure & DevOps
Follow me: Dev.to | GitHub | YouTube | LinkedIn | X

Top comments (1)

Collapse
 
morphoices profile image
MORPHOICΞS.

Terminal charts are a great example of making data useful without adding another layer of tooling—the real win is being able to spot patterns right where you’re already working. ~