DEV Community

jiil
jiil

Posted on

Generating Product Placeholders Locally in Go for E-Commerce Systems

In production e-commerce systems, placeholder images are commonly served via third-party services (e.g., placehold.it, unsplash.com) to mitigate UI flicker during asset loading. While convenient, this approach introduces unnecessary network dependencies, latency, and lack of brand consistency.

To eliminate these issues in our internal e-commerce platform — built with Go (backend) and Next.js (frontend) — we implemented a local, deterministic placeholder generation system.

The system runs during application startup and generates 40+ product image placeholders (400×400px, JPEG, 90% quality) in the ./uploads directory. Each image is customized with the product name and a branded gradient background. No external dependencies or runtime calls are required after generation.

Implementation Details

  • Language: Go 1.23
  • Packages used: image, image/jpeg, golang.org/x/image/font, golang.org/x/image/math/fixed
  • Image dimensions: 400×400 pixels
  • Output format: JPEG, quality 90%
  • Background: Vertical linear gradient from #6366F1 (indigo) to #8B5CF6 (violet)
  • Text:
    • Top: "E-Commerce" in white (#FFFFFF), basicfont.Face7x13
    • Bottom: Product name (e.g., "iPhone 15 Pro") in semi-transparent white (#FFFFFFCC)
  • Border: 1px white stroke (#FFFFFF64) with 20px rounded corners
  • File naming: Matches product catalog (e.g., iphone15_pro.jpg → "iPhone 15 Pro")
  • Idempotency: Generates only if file does not exist

Integration

The generation script is invoked as part of the application startup workflow:

make generate-placeholders
Enter fullscreen mode Exit fullscreen mode

This command is included in the make up sequence for development and as a pre-build step in Docker containers:

# In Dockerfile
RUN go build -o placeholders ./cmd/placeholders/main.go
RUN ./placeholders
Enter fullscreen mode Exit fullscreen mode

Code Snippet (Core Logic)

func generatePlaceholderImage(filePath, productName string) error {
    width, height := 400, 400
    img := image.NewRGBA(image.Rect(0, 0, width, height))
    bgColor1 := color.RGBA{99, 102, 241, 255}
    bgColor2 := color.RGBA{139, 92, 246, 255}
    for y := 0; y < height; y++ {
        ratio := float64(y) / float64(height)
        r := uint8(float64(bgColor1.R)*(1-ratio) + float64(bgColor2.R)*ratio)
        g := uint8(float64(bgColor1.G)*(1-ratio) + float64(bgColor2.G)*ratio)
        b := uint8(float64(bgColor1.B)*(1-ratio) + float64(bgColor2.B)*ratio)
        for x := 0; x < width; x++ {
            img.Set(x, y, color.RGBA{r, g, b, 255})
        }
    }
    d := &font.Drawer{
        Dst:  img,
        Src:  image.NewUniform(color.RGBA{255, 255, 255, 255}),
        Face: basicfont.Face7x13,
        Dot:  fixed.Point26_6{X: fixed.I(width/2 - 60), Y: fixed.I(height/2 - 40)},
    }
    d.DrawString("E-Commerce")
    productDrawer := &font.Drawer{
        Dst:  img,
        Src:  image.NewUniform(color.RGBA{255, 255, 255, 200}),
        Face: basicfont.Face7x13,
        Dot:  fixed.Point26_6{X: fixed.I(width/2 - len(productName)*3), Y: fixed.I(height/2 + 20)},
    }
    productDrawer.DrawString(productName)
    accentColor := color.RGBA{255, 255, 255, 100}
    cornerSize := 20
    for x := 0; x < width; x++ {
        img.Set(x, 0, accentColor)
        img.Set(x, height-1, accentColor)
    }
    for y := 0; y < height; y++ {
        img.Set(0, y, accentColor)
        img.Set(width-1, y, accentColor)
    }
    for i := 0; i < cornerSize; i++ {
        img.Set(i, i, accentColor)
        img.Set(width-1-i, i, accentColor)
        img.Set(i, height-1-i, accentColor)
        img.Set(width-1-i, height-1-i, accentColor)
    }
    file, err := os.Create(filePath)
    if err != nil {
        return err
    }
    defer file.Close()
    return jpeg.Encode(file, img, &jpeg.Options{Quality: 90})
}
Enter fullscreen mode Exit fullscreen mode

Conclusion
Local placeholder generation is a low-effort, high-impact optimization for e-commerce systems. It removes network fragility, improves UX predictability, and reinforces architectural autonomy. This approach is recommended for any system where image assets are known in advance and environment control is feasible.

Full implementation:
https://github.com/JIIL07/E-Commerce
Star it if you believe software should feel crafted — not just compiled.

Top comments (0)