Skip to content

Go Examples

Generate OG images using Go.

Basic Generation

go
package main

import (
	"bytes"
	"encoding/json"
	"io"
	"net/http"
	"os"
)

type OGImageRequest struct {
	Title    string `json:"title"`
	Subtitle string `json:"subtitle,omitempty"`
	Template string `json:"template,omitempty"`
	Theme    string `json:"theme,omitempty"`
}

func generateOGImage(params OGImageRequest) ([]byte, error) {
	apiKey := os.Getenv("OG_IMAGE_API_KEY")
	
	jsonData, err := json.Marshal(params)
	if err != nil {
		return nil, err
	}
	
	req, err := http.NewRequest("POST", "https://ogimageapi.io/api/generate", bytes.NewBuffer(jsonData))
	if err != nil {
		return nil, err
	}
	
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("X-API-Key", apiKey)
	
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	
	return io.ReadAll(resp.Body)
}

func main() {
	imageData, err := generateOGImage(OGImageRequest{
		Title:    "Hello from Go!",
		Subtitle: "Generated with OG Image API",
		Template: "default",
		Theme:    "dark",
	})
	
	if err != nil {
		panic(err)
	}
	
	os.WriteFile("og-image.png", imageData, 0644)
}

HTTP Handler

go
package main

import (
	"bytes"
	"encoding/json"
	"io"
	"net/http"
	"os"
)

func ogImageHandler(w http.ResponseWriter, r *http.Request) {
	title := r.URL.Query().Get("title")
	if title == "" {
		title = "Default Title"
	}
	
	subtitle := r.URL.Query().Get("subtitle")
	
	params := map[string]string{
		"title":    title,
		"subtitle": subtitle,
		"template": "default",
		"theme":    "dark",
	}
	
	jsonData, _ := json.Marshal(params)
	
	req, _ := http.NewRequest("POST", "https://ogimageapi.io/api/generate", bytes.NewBuffer(jsonData))
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("X-API-Key", os.Getenv("OG_IMAGE_API_KEY"))
	
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		http.Error(w, "Failed to generate image", http.StatusInternalServerError)
		return
	}
	defer resp.Body.Close()
	
	imageData, _ := io.ReadAll(resp.Body)
	
	w.Header().Set("Content-Type", "image/png")
	w.Header().Set("Cache-Control", "public, max-age=86400")
	w.Write(imageData)
}

func main() {
	http.HandleFunc("/og", ogImageHandler)
	http.ListenAndServe(":8080", nil)
}

With Gin Framework

go
package main

import (
	"bytes"
	"encoding/json"
	"io"
	"net/http"
	"os"

	"github.com/gin-gonic/gin"
)

type OGService struct {
	apiKey string
	client *http.Client
}

func NewOGService() *OGService {
	return &OGService{
		apiKey: os.Getenv("OG_IMAGE_API_KEY"),
		client: &http.Client{},
	}
}

func (s *OGService) Generate(params map[string]interface{}) ([]byte, error) {
	jsonData, _ := json.Marshal(params)
	
	req, _ := http.NewRequest("POST", "https://ogimageapi.io/api/generate", bytes.NewBuffer(jsonData))
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("X-API-Key", s.apiKey)
	
	resp, err := s.client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	
	return io.ReadAll(resp.Body)
}

func main() {
	r := gin.Default()
	ogService := NewOGService()
	
	r.GET("/og", func(c *gin.Context) {
		title := c.DefaultQuery("title", "Default Title")
		subtitle := c.Query("subtitle")
		
		imageData, err := ogService.Generate(map[string]interface{}{
			"title":    title,
			"subtitle": subtitle,
			"template": "default",
			"theme":    "dark",
		})
		
		if err != nil {
			c.String(http.StatusInternalServerError, "Failed to generate")
			return
		}
		
		c.Header("Content-Type", "image/png")
		c.Header("Cache-Control", "public, max-age=86400")
		c.Data(http.StatusOK, "image/png", imageData)
	})
	
	r.Run(":8080")
}

Concurrent Batch Generation

go
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"sync"
)

type Post struct {
	Slug    string
	Title   string
	Excerpt string
}

func generateForPost(post Post, wg *sync.WaitGroup, results chan<- error) {
	defer wg.Done()
	
	params := map[string]string{
		"title":    post.Title,
		"subtitle": post.Excerpt,
		"template": "blog",
		"theme":    "dark",
	}
	
	jsonData, _ := json.Marshal(params)
	
	req, _ := http.NewRequest("POST", "https://ogimageapi.io/api/generate", bytes.NewBuffer(jsonData))
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("X-API-Key", os.Getenv("OG_IMAGE_API_KEY"))
	
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		results <- fmt.Errorf("failed for %s: %w", post.Slug, err)
		return
	}
	defer resp.Body.Close()
	
	imageData, _ := io.ReadAll(resp.Body)
	
	err = os.WriteFile(fmt.Sprintf("./og/%s.png", post.Slug), imageData, 0644)
	if err != nil {
		results <- fmt.Errorf("failed to save %s: %w", post.Slug, err)
		return
	}
	
	results <- nil
}

func main() {
	posts := []Post{
		{Slug: "post-1", Title: "First Post", Excerpt: "Introduction"},
		{Slug: "post-2", Title: "Second Post", Excerpt: "More content"},
		{Slug: "post-3", Title: "Third Post", Excerpt: "Even more"},
	}
	
	os.MkdirAll("./og", 0755)
	
	var wg sync.WaitGroup
	results := make(chan error, len(posts))
	
	for _, post := range posts {
		wg.Add(1)
		go generateForPost(post, &wg, results)
	}
	
	wg.Wait()
	close(results)
	
	for err := range results {
		if err != nil {
			fmt.Println("Error:", err)
		}
	}
	
	fmt.Println("Done!")
}

Error Handling

go
func generateWithRetry(params map[string]interface{}, maxRetries int) ([]byte, error) {
	var lastErr error
	
	for i := 0; i < maxRetries; i++ {
		imageData, err := generateOGImage(params)
		
		if err == nil {
			return imageData, nil
		}
		
		lastErr = err
		
		// Exponential backoff
		time.Sleep(time.Duration(math.Pow(2, float64(i))) * time.Second)
	}
	
	return nil, fmt.Errorf("failed after %d retries: %w", maxRetries, lastErr)
}

Generate stunning Open Graph images programmatically.