Your own github shield server in 50 loc!
Tags: serverless, vercel, javascript, markdown
Published: 2022-05-20 13:17:07


Yes, 50 lines of code and you have your own custom shield/badge generator for your github READMEs!

And by server, I mean "serverless" - using [vercel](https://vercel.com/). 

---

#### Prerequsites:

If you don't already have one, create a *free* account at [vercel](https://vercel.com/). Then install the Vercel CLI and log in.

```bash
npm install -g vercel
vercel login
```

#### Create a new npm project:

```bash
mkdir mybadgeserver
cd mybadgeserver
npm init
```

#### Create the API endpoint:
The square brackets are required!

```bash
mkdir -p api/[label]/[value]
cd api/[label]/[value] 
touch index.js
```

Paste the following code into index.js

```js
module.exports = (req, res) => {
    const { label, value, ...options } = req.query
    const svg = makeShield(label, value, options) 
    res.setHeader('content-type', 'image/svg+xml')
    res.send(svg)
}

const defaultOptions = {
    labelColor: 'orange',
    valueColor: '#777',
    fontSize: '.8rem',
}

function makeShield(label, value, options = {}) {
    label = label ?? 'label'
    value = value ?? 'value'
    options = {...defaultOptions, ...options }
    console.log({options})
    return `<svg fill="none" viewBox="0 0 300 50" width="300" height="50" xmlns="http://www.w3.org/2000/svg">
        <style>
            shield {
                position: relative;
                margin: 5px;
                display:flex;
                color: white;
                font-size: ${options.fontSize};
                font-family: 'DejaVu Sans Mono', Verdana, DejaVu Sans, sans-serif;
            }
            label {
                background-color: ${options.labelColor};
                padding: 5px 10px;
                font-weight: 900;
                border-radius: 5px 0 0 5px;
            }
            value {
                position: relative;
                background-color: ${options.valueColor};
                padding: 5px 10px;
                border-radius: 0 5px 5px 0;
                left: 2px;
            }
        </style>
        <foreignObject width="100%" height="100%">
            <shield xmlns="http://www.w3.org/1999/xhtml">
                <label>${label}</label>
                <value>${value}</value>
            </shield>
        </foreignObject>
    </svg>`
}

```

And that's it! Fire-up the local dev server:

```
vercel dev
```

Test the endpoint in your browser `localhost:3000/api/label/value`

![address bar screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/79iycc25b4njp8xpqgin.png)

- Change `label` and `value` in the url to whatever you like!

- Change colors by appending `?labelColor=red&valueColor=green` to the url.

When you want to deploy to vercel just type:

```bash
vercel
```
This will give you a different *preview* url each time you run it.

To deploy to production and get a nice "static" url type:

```
vercel --prod
```

---

#### Bonus points:

You can eliminate the need for `api` in the url by creating a `vercel.json` in the project root (not in the api folder) with the following contents:

```json
{
    "rewrites": [
        {
            "source": "/:label/:value",
            "destination": "/api/:label/:value"
        }
    ]
}
```
--- 
DISCLAIMER: THIS IS GUIDE RATHER THAN A PRODUCTION READY SOLUTION - IT NEEDS TWEAKING - THE GENERATED SVGS ARE SURROUNDED BY TOO MUCH WHITE SPACE AND TEXT MAY CLIP IF TOO LONG.