Skip to main content

Generate customizable SVG badges for any project — offline, no network calls

Project description


Why badgeshield instead of shields.io?

shields.io is great — but it makes an HTTP call to an external server on every CI run.

badgeshield generates badges entirely offline:

  • No network calls — works in air-gapped CI, behind corporate proxies, and offline laptops
  • No rate limits — generate thousands of badges in a single run
  • No data sent externally — your version numbers, branch names, and repo stats stay local
  • Reproducible — same inputs always produce the same SVG, no caching surprises
# Generate every standard badge for your Python project in one command
badgeshield preset --all --output_path ./badges/ --format markdown

Drop the output straight into your README. No account needed, no tokens, no network.


📋 Table of Contents


📣 Overview

BadgeShield generates customizable SVG badges for GitLab, GitHub, and anywhere you can embed SVG. Five badge templates, four visual styles, 51 built-in colors, Pillow-powered font metrics, logo embedding with color tinting, automatic coverage badges from coverage.xml, and a Typer CLI with Rich progress bars and an SVG audit subcommand.


💡 Features

  • 5 templatesDEFAULT (two-part rectangular), PILL (fully rounded), CIRCLE, CIRCLE_FRAME with 11 PNG overlay frames, and BANNER (icon-zone + text).
  • 4 visual stylesFLAT, ROUNDED, GRADIENT, and SHADOWED via BadgeStyle enum or --style CLI flag.
  • 51 built-in colorsBadgeColor enum or any #RRGGBB hex string.
  • Accurate text sizing — font widths measured via Pillow (DejaVuSans) with a fallback estimator when Pillow is absent.
  • Logo support — embed PNG/JPEG logos with optional color tinting.
  • Coverage badge — read coverage.xml and auto-generate a correctly-colored badge in one command.
  • Concurrent batch — generate hundreds of badges in parallel from a JSON config; per-entry style overrides the CLI flag.
  • Modern CLI — Typer + Rich: progress bar, error panels, summary table, and audit subcommand.
  • Python API — import and generate from any script or CI job.

📌 Installation

pip install badgeshield

With logo tinting support (requires Pillow):

pip install "badgeshield[image]"

Upgrade:

pip install --upgrade badgeshield

🚀 Quick Start

Python API — DEFAULT template

from badgeshield import BadgeGenerator, BadgeStyle, BadgeTemplate

generator = BadgeGenerator(template=BadgeTemplate.DEFAULT, style=BadgeStyle.GRADIENT)
generator.generate_badge(
    left_text="build",
    left_color="#555555",
    right_text="passing",
    right_color="#44cc11",
    badge_name="build.svg",
    output_path="./badges",
)

style is set at generator construction time and applies to all badges that instance generates. Options: FLAT (default), ROUNDED, GRADIENT, SHADOWED.

PILL template

from badgeshield import BadgeGenerator, BadgeTemplate

generator = BadgeGenerator(template=BadgeTemplate.PILL)
generator.generate_badge(
    left_text="build",
    left_color="#555555",
    right_text="passing",
    right_color="#44cc11",
    badge_name="build-pill.svg",
)

CIRCLE template

from badgeshield import BadgeGenerator, BadgeTemplate

generator = BadgeGenerator(template=BadgeTemplate.CIRCLE)
generator.generate_badge(
    left_text="v2.1",
    left_color="#673ab7",
    badge_name="version.svg",
)

CIRCLE_FRAME template

from badgeshield import BadgeGenerator, BadgeTemplate, FrameType

generator = BadgeGenerator(template=BadgeTemplate.CIRCLE_FRAME)
generator.generate_badge(
    left_text="MH",
    left_color="#FF0000",
    badge_name="initials.svg",
    frame=FrameType.FRAME1,
    logo="path/to/avatar.png",
    logo_tint="#ffffff",
)

BANNER template

from badgeshield import BadgeGenerator, BadgeTemplate

generator = BadgeGenerator(template=BadgeTemplate.BANNER)
generator.generate_badge(
    left_text="badgeshield",
    left_color="#1a1a2e",
    right_text="v1.0",
    right_color="#16213e",
    badge_name="banner.svg",
)

📊 Coverage Badge

Generate a correctly-colored badge directly from a coverage.xml report — no manual color selection needed.

CLI

badgeshield coverage coverage.xml \
  --badge-name coverage.svg \
  --output-path ./badges

The color is chosen automatically based on these thresholds:

Coverage Color
≥ 90% #44cc11 green
≥ 80% #97ca00 yellow-green
≥ 70% #a4a61d yellow
≥ 60% #dfb317 orange
< 60% #e05d44 red

Use --metric branch to badge on branch coverage instead of line coverage.

Python API

from badgeshield import parse_coverage_xml, coverage_color
from badgeshield import BadgeGenerator, BadgeTemplate

pct = parse_coverage_xml("coverage.xml")          # e.g. 94.3
color = coverage_color(pct)                        # "#44cc11"

gen = BadgeGenerator(template=BadgeTemplate.DEFAULT)
gen.generate_badge(
    left_text="coverage",
    left_color="#555555",
    right_text=f"{pct:.0f}%",
    right_color=color,
    badge_name="coverage.svg",
    output_path="./badges",
)

🖥️ CLI Usage

Coverage badge

badgeshield coverage coverage.xml --badge-name coverage.svg --output-path ./badges

Use --metric branch for branch coverage, --left-text to change the label.

Single badge

badgeshield single \
  --left-text "coverage" \
  --left-color "#555555" \
  --right-text "94%" \
  --right-color "#44cc11" \
  --style gradient \
  --badge-name coverage.svg \
  --output-path ./badges

--style accepts flat (default), rounded, gradient, or shadowed (case-insensitive).

With a logo and links:

badgeshield single \
  --left-text "build" \
  --left-color "DARK_GREEN" \
  --right-text "passing" \
  --right-color "#44cc11" \
  --logo path/to/logo.png \
  --logo-tint "#ffffff" \
  --left-link "https://example.com/pipeline" \
  --badge-name build.svg

Framed circle:

badgeshield single \
  --left-text "MH" \
  --left-color "#673ab7" \
  --template CIRCLE_FRAME \
  --frame FRAME1 \
  --badge-name initials.svg

SVG audit

Verify that a generated SVG contains no external resource references:

badgeshield audit badges/build.svg          # exits 0 if clean, 1 if violations found
badgeshield audit badges/build.svg --json   # machine-readable JSON output

⚡ Batch Generation

CLI

badgeshield batch badges.json --output-path ./badges --max-workers 8

JSON config (badges.json)

[
  {
    "badge_name": "build.svg",
    "left_text": "build",
    "left_color": "GREEN"
  },
  {
    "badge_name": "coverage.svg",
    "left_text": "coverage",
    "left_color": "#555555",
    "right_text": "94%",
    "right_color": "#44cc11",
    "style": "gradient"
  },
  {
    "badge_name": "version.svg",
    "left_text": "v2.1.0",
    "left_color": "#673ab7"
  }
]

A per-entry "style" key overrides the CLI --style flag for that badge.

After the run, a Rich summary table shows which badges succeeded or failed.

Python API

from badgeshield import BadgeBatchGenerator, BadgeStyle, BadgeTemplate

batch = BadgeBatchGenerator(max_workers=4)
badges = [
    {"badge_name": "build.svg",    "left_text": "build",    "left_color": "GREEN", "output_path": "./out", "template": BadgeTemplate.DEFAULT, "style": BadgeStyle.FLAT},
    {"badge_name": "coverage.svg", "left_text": "coverage", "left_color": "#555",  "right_text": "94%", "right_color": "#44cc11", "output_path": "./out", "template": BadgeTemplate.DEFAULT, "style": BadgeStyle.GRADIENT},
]

try:
    batch.generate_batch(badges, progress_callback=lambda name: print(f"✓ {name}"))
except RuntimeError:
    for badge_name, error in batch._failures:
        print(f"✗ {badge_name}: {error}")

👪 Contributing

All contributions are welcome. Fork the repo, make your changes, and open a pull request. You can also open an issue with the label enhancement.

Don't forget to ⭐ star the project!

🔶 View all contributors


📃 Full Docs  ·  🔧 Report a Bug  ·  ⛪ Vertex AI Automations

(back to top)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

badgeshield-0.2.2.tar.gz (3.0 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

badgeshield-0.2.2-py3-none-any.whl (2.6 MB view details)

Uploaded Python 3

File details

Details for the file badgeshield-0.2.2.tar.gz.

File metadata

  • Download URL: badgeshield-0.2.2.tar.gz
  • Upload date:
  • Size: 3.0 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for badgeshield-0.2.2.tar.gz
Algorithm Hash digest
SHA256 1e8d4359d7aee84718750a52c82c753481a681b1eb99ddef3714de441505e535
MD5 25ba6f052542a29d6b4a719b7ca58261
BLAKE2b-256 80485119e7e38d56b40454474f0b8b96533a8a311709edd4be3a7876024494a4

See more details on using hashes here.

File details

Details for the file badgeshield-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: badgeshield-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 2.6 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for badgeshield-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 52751e4dd4afb15e6a02b37dc79f6a14e107ca05e958da05fa571a5b4f0cf093
MD5 4c5d8d460de46e9ca4f306549b51271e
BLAKE2b-256 b327eb75147a55c575af04557fe487ba6b9de2b96832405f3a2b8308e3ca0071

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page