Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: Supershields.io – smart, Lua-powered SVG status badges (supershields.io)
97 points by rlonn on Feb 24, 2022 | hide | past | favorite | 54 comments



Hi, I built supershields.io as an alternative to shields.io.

If you're interested in reading about the somewhat unorthodox product development process, I've written a blog article about it here: https://supershields.io/blog/1


Hey just a heads-up that the site is all messed up for me on iOS Safari: everything is huge, big horizontal scrollbar. Very hard to use.


Yeah, the service itself is kinda hard to use on a tiny screen so I haven't put a lot of effort into providing a good mobile user experience. I guess it would be useful to have a mobile-friendly version for people just checking out the service though.


Yeah I do almost all of my HN reading on my phone - so if stuff isn't readable on mobile it's hard for me to evaluate it.


Can I use supershields for an internal company metric to be displayed on a GitHub enterprise instance? I've tried using shields.io in the past for this and the API endpoint typically must be publicly accessible to make a metric button out of it.


There is a supershields Github app that you can install and then give access to one or more private Github repos. Then when you create Github badges on supershields.io you'll get the option to connect them with your private repo.

The app is here: https://github.com/marketplace/supershields

Not sure how Github enterprise works though. Can you use regular Github apps with your enterprise installation?


Great idea, Working on something for PNGs only.

but only for static data passed into query parameters.

https://bruzu.com


Ooh, you have a designer I see, neat!

Also, the API looks nice. Lots of image manipulation functionality. I've been thinking that the next step for Supershields would be some kind of lower level SVG creation API that lets people build their own SVGs from the ground up. This would also give them the ability to do more advanced stuff with images like your API can do (flipping and skewing etc.)


Thanks for trying.

Yes, I thing they should add a design editor too.


Hey, any interest in licensing a copy? I'm needing something exactly like this but at request volumes in the 100M/day range.


Hi Nick, I also sent you an email please check


Yes, lets talk DM on twitter @motyar


Any reason why the website is not mobile friendly?

Unless some css didn’t load up, I’ve got a huge horizontal bar.


You can't really use the service on a small screen, but I hear you. I have to provide at least a logged-out view that is mobile friendly.


Why can't it be used on a small screen? Also, many phones don't really have small screens...


It involves code editing, which is hard to do on a small screen.


You could fix the mobile site with as little as one line of CSS if you didn’t want to bother with media queries. `max-width: 100%` or `100vw` could be enough!


Funny, I've made lots of stuff responsive but at some point decided I had to have a minimum page width of 1050px.

Now when I remove that and add your "max-width: 100%" I don't see much of a problem. Sure, some content gets slightly misaligned on narrow screens but it looks pretty OK overall.

I just pushed the change now, should be visible within 5 minutes.


You'd be surprised how much code editing I get done on my phone these days - I ship small changes to my projects (including things like adding new badges to my READMEs) through the GitHub web interface quite often.


OK, I surrender!

Being horribly old and needing glasses to see anything small but never having any glasses around, I find that my phone is pretty much useless for work. I guess I'm an outlier here. I'll just see what I can do to improve the mobile UX!


You should just use bootstrap or zurb to avoid re-engineering mobile responsiveness


Nice, I wanted something like that to create badges for git deps in Clojure. Here is my attempt to do it using Supershields:

https://supershields.io/d1a18b018347defeec7b

Two questions:

1. text doesn't fit, how to fix that?

2. quote characters — «"» — get escaped as «"», how to avoid that?


Removing the html.unescape() seems to work


No it doesn't. The badge in the Test Script pane always shows correct quotes, but the publicly available one escapes the quotes. I added html.unescape thinking it will fix the issue, but it didn't. Now I removed unescape again, and it's still broken.


Try now!

The backend was a bit over-zealous about the HTML escaping...


Fantastic, thanks a lot!


Oh, sorry, I'll investigate it. BRB.


Does GitHub let you embed and keep these as smart? (SVG auto-updates for eg?) My understanding was that Github proxies all SVGs and renders them as PNG/JPG at their end.


You can put external links into e.g. your Github README.md to display badges but yes, Github seem to have some silly policy of not allowing people to inject executable Javascript into their website so you can't embed things using <object> tags, or similar. You have to use <img> which means no JS included in the badge SVG will be executed => no automatic updates.


Is it really a silly policy? I like that a lot.


Of course it is silly - it infringes on my personal freedom not to be able to execute arbitrary code on the computers of people visiting Github!


Github does proxy SVGs, but it doesn't rasterize them.

If you're interested in embedding something like this on GitHub then you might want to check out Repography [1]. There are only a few styles of dashboards at the moment but I'm working on others.

[1] https://repography.com/


Yep

Here’s an example of SVG animation https://github.com/sindresorhus/css-in-readme-like-wat

Also see https://badgen.net which is another alternative to the original post.


You implemented all the missing stuff with badges and its awesome.

I wouldn't ever pay for stuff like this tho, but I hope that is just me.


Thanks :) To be honest, I'm not sure there is a viable business here. I think perhaps making it more niched, like going for financial badges only and providing lots of templates for those types of badges, may be smarter. But it's also more boring so I don't plan on doing that. at the moment, I'll be happy if people just use the service.


IMO the horizontal margins around text are way too wide, which makes the badges look ugly (subjective) and space-inefficient when placed in a row (objective). Faithfully copying the shields.io style would be a lot better. Their layout appears to be

  6px LHS 4px | 4px RHS 6px


Yeah, the issue is (disclaimer: I might have missed something vital here) that it is very hard to know exactly how wide text is when rendered inside the SVG. Some characters take less space than others and the safest way to determine the width of a string when it is rendered is to actually render it. This, of course, is hard to do on the server side. I'm not sure what shields.io does (I'll take a new look at it though) but given that their badges contain more predictable text strings (at least on the left-hand-side it tends to be static text) it is easier there to adjust the size of the SVG manually whe you create a new badge. Supershields badges, on the other hand, can contain very different text strings and there is no way to know what the text will be before you execute the Lua script.

Hmm, a bit rambling response, this one. I hope you get what I mean (and that I'm not completely clueless - have to look at the shields.io code again!)


I took a look. The rendering code of shields.io is here: https://github.com/badges/shields/blob/779c1ffaadfcd53ac20b5... text width is computed in preferredWidthOf, which computes the width of the text in 11px Verdana, either normal or bold: https://github.com/badges/shields/blob/779c1ffaadfcd53ac20b5... The anafanafo dependency is doing all the heavy lifting: https://www.npmjs.com/package/anafanafo


Wow, thanks for that investigation. I'm pretty sure I looked at this at some point, and realized shields.io was using some esoteric NPM package that I would not find (or maybe I actually searched) the equivalent of for Golang, so I had to do something simpler.

I looked at the anafanafo package now and one of the first things they say in the presentation is "Built with Shields in mind"... So this package was custom made for shields.io, apparently. From a very quick check it seems to be a non-trivial amount of code, so not super simple to just port to Golang.

I don't want to have to start running Node and NPM packages, but would be very interested in any way to get this kind of functionality in a Go program.


I took a quick glance at anafanafo and couldn't tell if porting to Go would be easy, since the structure seems slightly convoluted. Anyway, if the lookup table approach used by anafanafo isn't easy to implement, there's always the rendering approach, using something like Cairo. Code I whipped up in a few minutes:

  package main
  
  import (
          "fmt"
  
          "github.com/gotk3/gotk3/cairo"
  )
  
  var _cr *cairo.Context
  
  func init() {
          _cr = cairo.Create(cairo.CreateImageSurface(cairo.FORMAT_RGB24, 1000, 50))
          _cr.SelectFontFace("Verdana", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
          _cr.SetFontSize(11)
  }
  
  func measureTextWidth(t string) float64 {
          return _cr.TextExtents(t).Width
  }
  
  func main() {
          measureAndPrint := func(t string) {
                  fmt.Println(t, measureTextWidth(t))
          }
          measureAndPrint("build")
          // build 24.7177734375
          measureAndPrint("passing")
          // passing 39.767578125
  }

Not sure if performance would be acceptable, though.


That looks interesting. I'm installing Cairo right now - a bit of a beast though. I'll test it but might try to port the anafanafo functionality anyway. It'd be very nice to just have 100 lines of Go code and a JSON data file to deal with.


Hmm, seems they just have a couple of JSON files specifying the widths of different characters in a few standard fonts. I may take a shot at porting the basic functionality to golang.


Hi cool project. Congrats on finishing.

Some questions about lua:

- What dev environment do u prefer? When I looked last time I didn't really see a dedicated IDE for lua, mostly just plugins for vim/emacs.

- Did you consider lua in nginx? (Or what are you thoughts on it).

- Did you consider moonscript? (Or what are you thoughts on it)


I'm generally using Visual Studio Code for all my development. Really like it.

I chose https://github.com/yuin/gopher-lua as the Lua engine because it is Golang-based, while the Nginx Lua VM is C, unless I'm mistaken. Using gopher-lua is just easier when I'm working in a Golang project. I only have to work in a single language and dev environment for all the backend work. Makes both development and testing easier.

Moonscript I might have heard of, but I have no experience with it. I did not consider it here, and I would rarely consider any niche scripting language for a solution I want others to use. It just introduces an unnecessary barrier to adoption.


Something I've always wondered about these shields... How do you ensure the platforms where users embed them don't cache the images in their CDNs?

Is it just a matter of setting headers?


If you load http://example.com and the HTML there includes an image tag that says '<img src="http://othersite.com/image.jpg">' it means your browser will connect to othersite.com and ask that site for the image. It will not ask example.com.


I'm asking about what happens when, for example, you embed a dynamic SVG badge in your GitHub readme.

Doesn't GitHub cache every image in their own CDN for security and control purposes?


You can't use <object>, <iframe> etc tags to embed pictures in your Github README, so you don't get automatic updates there no matter what (i.e. images would only refresh on page load). I don't know if Github proxies and caches <img> contents, or how long they cache it for but I haven't personally seen any delays when I've updated images used in READMEs.

But to repeat: auto-updating will not work for Github-hosted content AFAIK.


How'd you sandbox Lua?


I write a little about it in the blog post: https://supershields.io/blog/1

TL;DR is that most Lua engines seem to offer pretty weak support for sandboxing, unfortunately. Gopher-lua, that Supershields is using, makes it hard to adopt a whitelist-approach where you disable more or less everything and then enable just the functionality you want. Blacklisting (where you specify everything you want to disable) is fairly simple though, but not as secure of course.

For Supershields I have used a combination of blacklisting and running the scripts on serverless instances (AWS Lambda), which limits the impact of a breach.


Looking at this docs page[1], it doesn't look like the execution environment gets reset completely between each request. Do you partition free/paying users or public/private repos? It seems like an attacker could gain a foothold for longer than just their request with malicious code.

[1] https://docs.aws.amazon.com/lambda/latest/dg/runtimes-contex...


That's a good observation. I don't currently do any partitioning and I think I have to read up a bit on exactly how Lambda executes Go functions. If they keep the program state between executions there are probably some cleanup I should be doing. If not, I think I'm safe as script code and everything related to a new script execution gets sent as parameters in the Lambda invocation.

Edit: I'm going to add some cleanup regardless.


Why Lua?


It is small, fast, easy to use and easy to embed.




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: