Skip to content

Repository files navigation

Scanned with LGTM Security

Doodlebug

Doodlebug

Open-source hand-drawn GitHub stats cards for your README.

Doodlebug turns your GitHub activity into hand-drawn SVG cards — every stroke is generated with rough.js and a per-user seed, with real handwriting fonts embedded, so cards render anywhere (including GitHub READMEs) and no two look exactly alike.

License: MIT Next.js 15 TypeScript rough.js CI

A DevsBazaar product — open sourced.

Live site · Docs · Themes · Report a bug


Why Doodlebug exists

Every README has the same stats card on it. They are competently drawn, identical to each other, and forgettable.

Doodlebug draws yours by hand instead. Nothing is a template: every rectangle, ring, arc and icon is generated stroke by stroke with rough.js from a seed derived from your username, so your card is wobbly in a way nobody else's is. The handwriting fonts are embedded in the SVG rather than linked, which is what lets the result survive GitHub's image proxy.

It is free, it needs no token to get started, and the whole thing — the card engine, the builder, the accounts, the caching — is in this repository. Run it hosted, or self-host the lot.


Cards

stats streak
languages graph
repo skills

trophies

activity

project achievements

portfolio linkedin email

Type What it draws
stats Stars, commits, PRs, issues (+ optional merged/reviews/followers/repos/forks) and a hand-drawn rank ring
langs Top languages as sketched bars, a donut, a pie or a compact strip
streak Total contributions, current streak in a flame ring, longest streak
activity A wobbly contribution heatmap (8–53 weeks)
graph Hand-drawn line chart of daily contributions (7–120 days)
trophies Shields ranked C → SS for stars, commits, PRs, issues, followers, repos, streaks
repo Pin any repository: description, language, stars, forks, topics
banner Wide handwritten header with your name, tagline and doodles
skills Your stack as sketched stickers
note A taped sticky note with handwritten text
project Your own title, description, tags, link and ribbon badge — optionally merged with live repo stats
achievements Hackathon wins, awards, certifications as numbered hand-drawn medals
link A hand-drawn button for portfolio / LinkedIn / email — wrap it in a link

Usage

https://doodlebug.tarinagarwal.in/api/card/<type>?username=<login>&theme=<theme>&…
[![My stats](https://doodlebug.tarinagarwal.in/api/card/stats?username=octocat&theme=chalkboard)](https://github.com/octocat)

Themes: paper notebook grid sticky kraft sakura forest ocean candy chalkboard blueprint midnight graphite dracula — or override any colour with bg, ink, accent, accent2, muted (hex without #). Browse them all on the themes page.

theme=auto ships a single card that recolours itself: drawn in the paper palette, swapped to midnight under prefers-color-scheme: dark. Worth knowing that an SVG loaded through <img> follows the reader's browser/OS setting rather than GitHub's own light/dark toggle, so it suits most readers but not every one.

Saved cards get a short, stable URL

Save a design in the dashboard and it is also served from a fixed address:

https://doodlebug.tarinagarwal.in/c/<saved-card-id>.svg

Paste that into your README once. Restyling the card in the dashboard updates every README using it — you never edit the markdown again. Query params still work and take precedence, so ?theme=midnight previews a variant without saving a second card.

Every parameter is documented on the docs page. The dashboard has a guided builder (sidebar of card types, quick-start presets, live preview, one-click markdown), and every design can be saved and edited later under My cards.

Public data vs. your own token

Cards work for any public GitHub user out of the box using GitHub's public API and the public contribution graph. Those endpoints have shared rate limits, so under heavy traffic a card can temporarily show a "rate limited" doodle.

Create a free Doodlebug account, save your GitHub username and (optionally) a personal access token: it is stored AES-256-GCM encrypted, only decrypted in memory to talk to api.github.com, and Doodlebug will use it whenever anyone loads a card for your username. That unlocks the GraphQL API — private-contribution counts, accurate language bytes, review counts and no shared limits.

Self-hosting

git clone https://github.com/tarinagarwal/Doodlebug
cd Doodlebug
pnpm install
cp .env.example .env.local   # fill in MongoDB, SMTP, secrets
pnpm dev
pnpm test        # card rendering + library unit tests (vitest, no DB or network needed)
pnpm lint        # eslint
pnpm typecheck   # tsc --noEmit
Variable Purpose
MONGODB_URI MongoDB connection string (accounts, saved cards)
JWT_SECRET Session signing secret (≥32 chars)
ENCRYPTION_KEY 64 hex chars — AES-256-GCM key for stored GitHub tokens
APP_URL Public URL, used in emails and generated snippets
SMTP_HOST SMTP_PORT SMTP_USER SMTP_PASS MAIL_FROM Verification / password-reset email
GITHUB_TOKEN Server-wide fallback token for public fetching. Strongly recommended: a classic PAT with no scopes ticked lifts the rate limit from 60/hr to 5,000/hr and switches every visitor onto the GraphQL path
UPSTASH_REDIS_REST_URL / UPSTASH_REDIS_REST_TOKEN Optional Redis for the GitHub cache and rate-limit buckets. Falls back to MongoDB when unset. Use a regional database in the same region as your deployment, with eviction enabled
OPENAI_API_KEY Optional — only for pnpm gen:assets (illustration generation)

Deploys to Vercel with zero config.

How it is built

  • Next.js 15 (App Router) + TypeScript + Tailwind v4 — the UI itself is hand-drawn too (wobbly borders, tape, marker highlights).
  • rough.js generator running server-side to sketch every rectangle, ring, arc and icon; deterministic per user via seeded randomness.
  • Embedded fonts — Patrick Hand, Caveat and Kalam subset to Latin and base64-embedded so SVGs render inside GitHub's image proxy.
  • GitHub data — GraphQL when a token is available, REST + the public contribution graph otherwise; results cached in MongoDB with stale-while-revalidate semantics.
  • Auth — email + password, SMTP verification, JWT session cookies, bcrypt, per-IP rate limiting. Sessions carry a tokenVersion, so a password reset or change strands every session issued before it — including one an attacker is holding.
  • Card hot path — no blocking database work: flood protection is an in-process counter, and render stats are buffered in memory and flushed as one bulk write after the response is sent. The tight limit sits on uncached GitHub lookups, which is where the cost actually is, so a popular README behind GitHub's camo proxy is never throttled for being popular.
  • Tests — every card type is rendered against a fixture bundle and checked for well-formed SVG, XML escaping, determinism and degenerate input (empty accounts, zero-width slices, 5,000-character text), plus golden snapshots. CI runs typecheck, lint, tests and a build on every push and PR.

Contributing

Issues and pull requests are welcome. The card renderers are pure functions of (bundle, URLSearchParams), so a new card type is one file in src/lib/cards/ plus an entry in src/lib/cards/meta.ts — and the test suite renders every registered type automatically, so coverage comes for free.

pnpm test        # 93 tests, no database or network needed
pnpm lint
pnpm typecheck

Please report security vulnerabilities privately to tarinagarwal@gmail.com rather than in a public issue.

Questions, ideas or commercial enquiries: tarinagarwal@gmail.com


License

MIT — use it, fork it, sell it. No licence fee, no attribution required.

Built and open sourced by DevsBazaar

About

Hand-drawn GitHub stats cards for your README — stats, streaks, languages, trophies, banners. Built with Next.js + rough.js.

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages