Serve a dynamic SVG badge

In this example, we use Modal’s webhook capability to host a dynamic SVG badge that shows you the current # of downloads for a Python package.

First let’s start off by creating a Modal stub, and defining an image with the Python packages we’re going to be using:

from modal import Image, Stub, web_endpoint

stub = Stub(
    "example-web-badges",
    image=Image.debian_slim().pip_install("pybadges", "pypistats"),
)

Defining the web endpoint

In addition to using @stub.function() to decorate our function, we use the @modal.web_endpoint decorator (learn more), which instructs Modal to create a REST endpoint that serves this function. Note that the default method is GET, but this can be overridden using the method argument.

@stub.function()
@web_endpoint()
async def package_downloads(package_name: str):
    import json

    import pypistats
    from fastapi import Response
    from pybadges import badge

    stats = json.loads(pypistats.recent(package_name, format="json"))
    svg = badge(
        left_text=f"{package_name} downloads",
        right_text=str(stats["data"]["last_month"]),
        right_color="blue",
    )

    return Response(content=svg, media_type="image/svg+xml")

In this function, we use pypistats to query the most recent stats for our package, and then use that as the text for a SVG badge, rendered using pybadges. Since Modal web endpoints are FastAPI functions under the hood, we return this SVG wrapped in a FastAPI response with the correct media type. Also note that FastAPI automatically interprets package_name as a query param.

Running and deploying

We can now run an ephemeral app on the command line using:

modal serve badges.py

This will create a short-lived web url that exists until you terminate the script. It will also hot-reload the code if you make changes to it.

If you want to create a persistent URL, you have to deploy the script. To deploy using the Modal CLI by running modal deploy badges.py,

Either way, as soon as we run this command, Modal gives us the link to our brand new web endpoint in the output:

web badge deployment

We can now visit the link using a web browser, using a package_name of our choice in the URL query params. For example:

  • https://YOUR_SUBDOMAIN.modal.run/?package_name=synchronicity
  • https://YOUR_SUBDOMAIN.modal.run/?package_name=torch