DEV Community

Cover image for Building Bags.fm Embeds: A Free Tool to Make Crypto Community Support Visible
Sivaram
Sivaram

Posted on

Building Bags.fm Embeds: A Free Tool to Make Crypto Community Support Visible

TL;DR: Token addresses are forgettable. Community support shouldn't be. I built Bags.fm Embeds — a free tool that turns wallet addresses into real-time badges showing lifetime earnings. It took two weekends and taught me a lot about Go concurrency.


The Problem

If you've ever shared a Solana token address, you know the drill:

9XzKDJ9wP9yqi9G5okp9UFNxFuhqyk5GNyUnnBaRBAGS
Enter fullscreen mode Exit fullscreen mode

That's it. That's the tweet.

A 44-character string that tells you nothing about:

  • The thousands of dollars in fees this token generated
  • The creators being supported by the community
  • The active, growing ecosystem around this project

The address is static, but the community is alive.


The Inspiration

GitHub badges:

![npm version](https://img.shields.io/badge/npm-v1.0.0-blue)
![build passing](https://img.shields.io/badge/build-passing-brightgreen)
Enter fullscreen mode Exit fullscreen mode

They work because they make boring metadata visual and shareable.

What if crypto earnings had the same treatment? A badge that shows:

  • Total lifetime fees earned
  • Who's receiving those fees
  • Real-time updates as the community grows

What I Built

5 embed types:

Type Use Case
Stats Card Widget Full stats for websites
Fee Badge (Recipient) Creator earnings display
Fee Badge (Project) Total project fees
Mini Badge (Recipient) Compact for GitHub/Twitter
Mini Badge (Project) Compact for project pages

Key insight: SVG badges work everywhere — GitHub, Notion, Twitter cards, Discord. No JavaScript required. Just an image URL.

See live examples here.


The Technical Stuff

Why Go?

Aspect Next.js + Vercel Go + Railway
Cold starts Yes No
Memory ~100MB ~5-10MB
Concurrency Good Excellent
Monthly cost $20+ $5-20

For a service serving SVG badges in <50ms, Go was the clear winner.

The Background Worker Pattern

The badges show USD values → need current SOL price → can't fetch on every request.

Solution: A background goroutine that fetches SOL price every 15 seconds:

func (p *PriceService) StartWorker(ctx context.Context) {
    ticker := time.NewTicker(15 * time.Second)
    defer ticker.Stop()

    for {
        select {
        case <-ctx.Done():
            return
        case <-ticker.C:
            p.fetchAndCachePrice()
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

The architecture:

HTTP Server (main goroutine)
    ↓ reads from
Redis (shared state)
    ↑ writes to
Background Worker (price goroutine)
Enter fullscreen mode Exit fullscreen mode

If Jupiter's API goes down? HTTP requests keep serving cached data. The worker tries Binance, then CoinGecko. Users never notice.

5 Layers of Caching

  1. Browser (60s) — Repeat visitors don't hit server
  2. Cloudflare CDN (60s) — Global edge caching
  3. Redis — Different TTLs per data type
  4. Fallback cache — Last known values
  5. Hardcoded defaults — When everything fails

Result: 99% of requests served from cache in <50ms.

SVG Generation

func generateBadge(data TokenData, theme string) string {
    bgColor := "#1a1a1a"
    textColor := "#ffffff"
    if theme == "light" {
        bgColor, textColor = "#ffffff", "#1a1a1a"
    }

    return fmt.Sprintf(`<svg xmlns="http://www.w3.org/2000/svg"
        width="320" height="52">
        <rect fill="%s" rx="8" width="320" height="52"/>
        <text fill="%s" x="16" y="32">
            Lifetime Fees: $%s
        </text>
    </svg>`, bgColor, textColor, formatCurrency(data.FeesUSD))
}
Enter fullscreen mode Exit fullscreen mode

Valid SVG that works as an <img> tag anywhere.


The Growth Flywheel

Projects share embeds
    → Visibility for platform
        → New users discover it
            → More trades, more fees
                → Creators earn more
                    → More projects join
                        → More embeds
Enter fullscreen mode Exit fullscreen mode

Every badge is passive marketing.


Lessons Learned

1. Solve the Visibility Problem

The biggest issue wasn't technical — impact was invisible. Badges make the intangible tangible.

2. Meet People Where They Are

SVG badges work in GitHub, Twitter, Notion, Discord, and websites. One format, everywhere.

3. Design for Failure

External APIs will go down. Fallback sources + cached data + graceful degradation = users never notice.

4. Concurrency Simplifies Architecture

Background worker pattern eliminated race conditions, timeouts, and request blocking.

5. Free Tools Win

Free tools get adopted faster. The goal is ecosystem growth, not revenue.


Try It

Live: bags.sivaramp.com

Examples: bags.sivaramp.com/examples

Steps:

  1. Paste token address (must end in BAGS)
  2. Pick embed type
  3. Copy code
  4. Paste anywhere

Tech Stack

Backend:  Go 1.21+ / Gin
Frontend: React / Vite / TypeScript
Cache:    Redis
CDN:      Cloudflare
Hosting:  Railway
Data:     Bags SDK, DexScreener, Jupiter
Enter fullscreen mode Exit fullscreen mode

What do you think? I'd love to hear if you've built similar tools for making data visible. Drop a comment below!

If you're building in the Solana ecosystem, try out the embeds and let me know how you use them.

Top comments (0)