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


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 a weekend, taught me a lot about Go concurrency, and might actually help grow an entire ecosystem.


The Problem Nobody Talks About

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

9XzKDJ9wP9yqi9G5okp9UFNxFuhqyk5GNyUnnBaRBAGS

That’s it. That’s the tweet. A 44-character string that tells you absolutely nothing.

No story. No context. No indication that this token has generated thousands of dollars in fees for creators. No signal that hundreds of community members are actively supporting this project.

The address is static, but the community is alive.

I kept seeing this disconnect in the Bags.fm ecosystem — a platform where token trading generates fee revenue that flows back to creators. Projects were sharing contract addresses, but the impact of community support was invisible.

What if you could see it?


The “Aha” Moment

I was browsing GitHub one day and noticed those little badges everyone uses:

npm version build passing license MIT

They’re everywhere because they work. They take boring metadata (version numbers, build status) and make it visual and shareable.

What if Bags.fm had something like this? A badge that shows:

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

Not a screenshot. Not a manual update. A live, embeddable badge that grows with the community.


What I Built

Bags.fm Embed Generator — five different embed types for different use cases:

1. Stats Card Widget

The full experience. Token name, logo, lifetime fees in USD and SOL, all fee recipients with their profiles, plus live market data (price, volume, market cap).

Perfect for websites and landing pages.

Stats Card Widget

2. Fee Badge (Recipient)

Shows a creator’s total earnings from a token. “I’ve earned $2,221 from this project.”

Fee Badge Recipient

3. Fee Badge (Project)

Shows total fees generated by a token. “This project has generated $5,000 for its creators.”

Fee Badge Project

4. Mini Badge (Recipient)

Compact version for GitHub READMEs, Twitter bios, or anywhere space is tight.

Mini Badge Recipient

5. Mini Badge (Project)

Compact token badge for project pages.

Mini Badge Project

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

Check out live examples to see them in action.

See It In Action


The Technical Journey

I’ll be honest: this could have been a simple weekend project. Fetch data, render HTML, done.

But I wanted it to be fast and reliable. And that led me down some interesting rabbit holes.

Why Go Instead of Node/Python?

My first instinct was Next.js on Vercel. I’ve built a dozen projects that way. But the requirements didn’t fit:

AspectNext.js + VercelGo + Railway
Cold startsYes (serverless)No (always running)
Memory usage~100MB~5-10MB
Response timeGoodExcellent
ConcurrencyGoodExcellent (goroutines)
Monthly cost$20+$5-20

For a service that needs to serve SVG badges in under 50ms with thousands of concurrent requests, Go was the obvious choice. A single binary, minimal memory footprint, and goroutines for concurrency.

The Background Worker Pattern

Here’s where it got interesting. The badges need to show USD values, which means I need the current SOL price. But I can’t fetch it on every request — that would be slow and hit rate limits.

Solution: a background goroutine that fetches the SOL price every 15 seconds and writes it to Redis.

┌─────────────────────────────────────────────────┐
│  Main Goroutine (HTTP Server)                   │
│  - Serves requests instantly                    │
│  - Reads from Redis (non-blocking)              │
│  - Never waits for external APIs                │
└─────────────────────────────────────────────────┘

                        │ Reads from

┌─────────────────────────────────────────────────┐
│              Redis (Shared State)               │
│  - SOL price (updated every 15s)                │
│  - Token metadata (10min TTL)                   │
│  - Fee data (2min TTL)                          │
└─────────────────────────────────────────────────┘

                        │ Writes to
┌─────────────────────────────────────────────────┐
│  Background Worker Goroutine                    │
│  - Runs every 15 seconds                        │
│  - Fetches from Jupiter → Binance → CoinGecko   │
│  - Never blocks HTTP requests                   │
└─────────────────────────────────────────────────┘

The beauty: if Jupiter’s API goes down, HTTP requests keep serving cached data. The background worker will try Binance, then CoinGecko. Users never notice.

The Caching Strategy

Five layers of caching:

  1. Browser cache (60s) — Repeat visitors don’t hit the server
  2. Cloudflare CDN (60s) — Global edge caching
  3. Redis — Different TTLs for different data:
    • SOL price: 15s
    • Token metadata: 10min
    • Fee data: 2min
    • Market data: 1min
  4. Fallback cache — Last known values when APIs fail
  5. Hardcoded fallback — Reasonable defaults when everything is down

The result? 99% of requests are served from cache in under 50ms.

SVG Generation in Go

Generating SVGs server-side was surprisingly fun. No templating library, just string building with proper escaping:

func generateBadge(data TokenData, theme string) string {
    bgColor := "#1a1a1a"
    textColor := "#ffffff"
    if theme == "light" {
        bgColor = "#ffffff"
        textColor = "#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" font-size="14">
            Lifetime Fees: $%s
        </text>
    </svg>`, bgColor, textColor, formatCurrency(data.FeesUSD))
}

The output is a valid SVG that works as an <img> tag anywhere on the web.


The Community Flywheel

Here’s what I find most exciting about this project: it creates a growth flywheel.

Projects share embeds
    → Visibility for Bags.fm
        → New users discover the platform
            → More trades, more fees
                → Recipients earn more
                    → More projects join
                        → More embeds shared

Every badge is passive marketing. Every embed is a data point showing that Bags.fm actually delivers value to creators. The more successful a token becomes, the more impressive its badge, the more likely it is to attract new community members.

The best part: I built the tool, but the community creates the growth.


Lessons Learned

1. Solve the Visibility Problem

The biggest issue wasn’t technical — it was that impact was invisible. Community members were contributing, but there was no tangible proof. Badges make the intangible tangible.

2. Meet People Where They Are

SVG badges work in GitHub READMEs, Twitter, Notion, Discord, and websites. I didn’t build five different integrations; I built one format that works everywhere.

3. Design for Failure

External APIs will go down. The Jupiter price API rate-limited me during development. DexScreener had a brief outage. Because I planned for failure (fallback sources, cached data, graceful degradation), users never noticed.

4. Concurrency Simplifies Architecture

The background worker pattern eliminated an entire class of problems. No race conditions on price fetches. No request timeouts waiting for external APIs. Clean separation of concerns.

5. Free Tools Win

I could have built this as a SaaS with pricing tiers. But the goal isn’t revenue — it’s ecosystem growth. Free tools get adopted. And if Bags.fm grows, everyone benefits.


Try It Yourself

Live Demo: bags.sivaramp.com

Examples: bags.sivaramp.com/examples

How it works:

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

What’s Next

I’m considering a few enhancements based on early feedback:

  • Custom colors — Let projects match their brand
  • Animated badges — Show price changes in real-time
  • Embed analytics — Track impressions and clicks
  • Multi-token portfolios — Show total earnings across multiple tokens

But honestly? The MVP is working. Projects are starting to use it. The flywheel is starting to turn.

Sometimes the best next step is to get out of the way and let the community take over.


Final Thoughts

Building developer tools for crypto is an interesting space. The ecosystem is young, the tooling is sparse, and there’s real opportunity to make an impact.

This project took about two weekends. The hardest part wasn’t the code — it was identifying the right problem to solve. Once I realized that visibility was the gap, everything else fell into place.

If you’re building in this space, my advice: look for the invisible things. The data that exists but isn’t surfaced. The impact that’s real but not measurable. Make it visible.

That’s where the leverage is.


If you found this useful, consider sharing it with someone building in the Solana ecosystem. And if you try out the embed generator, I’d love to see how you use it!


Tech Stack:

  • Backend: Go 1.21+ with Gin
  • Frontend: React + Vite + TypeScript
  • Cache: Redis
  • CDN: Cloudflare
  • Hosting: Railway
  • Data: Bags SDK, DexScreener, Jupiter, Binance, CoinGecko