Unified Go library for multi-provider AI image generation with automatic cloud storage upload.
Stop copy-pasting the same OpenAI + GCS pipeline across your Go projects. imagen provides a clean Provider / Storage interface so you can swap AI providers, change storage backends, and generate-and-store images in a single call.
package main
import (
"context"
"fmt"
"log"
"github.com/mnkrana/imagen"
)
func main() {
cfg := imagen.LoadConfigFromEnv()
client, err := imagen.NewClientFromConfig(cfg)
if err != nil {
log.Fatalf("client: %v", err)
}
result, err := client.GenerateAndStore(context.Background(), &imagen.Request{
Prompt: "a serene mountain landscape at sunset, photorealistic",
})
if err != nil {
log.Fatalf("generate: %v", err)
}
fmt.Println("Generated image:")
fmt.Printf(" URL: %s\n", result.URL)
fmt.Printf(" Size: %d bytes\n", result.Size)
}Run it:
cp .env.example .env # fill in your keys and bucket
go run .go get github.com/mnkrana/imagenRequires Go 1.26+.
imagen auto-loads a .env file from the current directory if present. Set these variables:
| Variable | Required | Default | Description |
|---|---|---|---|
OPENAI_API_KEY |
for OpenAI | — | OpenAI API key |
STABILITY_API_KEY |
for Stability | — | Stability AI API key |
GCS_BUCKET |
yes | — | Google Cloud Storage bucket name |
IMAGEN_PROVIDER |
no | openai |
Provider: openai or stability |
IMAGEN_MODEL |
no | gpt-image-2 |
Model name |
IMAGEN_SIZE |
no | 1024x1024 |
Output size |
IMAGEN_QUALITY |
no | standard |
Quality: standard or hd |
IMAGEN_OUTPUT_FORMAT |
no | webp |
Output format (Stability: png, webp, jpeg) |
IMAGEN_HTTP_TIMEOUT |
no | 90s |
HTTP client timeout |
GCS_OBJECT_PREFIX |
no | images/ |
GCS object path prefix |
STABILITY_ENDPOINT |
no | https://api.stability.ai/v1 |
Stability API base URL |
STABILITY_MODEL |
no | stable-diffusion-xl-1024-v1-0 |
Stability model ID |
STABILITY_CFG_SCALE |
no | 7.0 |
Classifier-free guidance scale |
STABILITY_STEPS |
no | 30 |
Number of inference steps |
STABILITY_STYLE_PRESET |
no | — | Style preset (photographic, digital-art, anime, etc.) |
provider := imagen.NewOpenAIProvider("sk-...",
imagen.WithOpenAIModel("gpt-image-2"),
imagen.WithOpenAISize("1792x1024"),
imagen.WithOpenAIQuality("hd"),
)
storage := imagen.NewGCSStorage("my-bucket",
imagen.WithGCSObjectNamer(func(r *imagen.Result) string {
return fmt.Sprintf("generated/%d%s", time.Now().UnixNano(), ".png")
}),
)
client := imagen.NewClient(provider, storage)┌──────────┐ ┌──────────────────┐ ┌─────────────┐ ┌──────────┐
│ Request │───▶│ Client │───▶│ Provider │───▶│ Result │
│ (prompt) │ │ GenerateAndStore│ │ (OpenAI / │ │ (bytes) │
└──────────┘ │ │ │ Stability)│ └──────────┘
│ │ └─────────────┘ │
│ │ ▼
│ │ ┌─────────────┐ ┌──────────┐
│ │───▶│ Storage │───▶│Storage │
│ │ │ (GCS) │ │Result │
└──────────────────┘ └─────────────┘ │(URL) │
└──────────┘
Two core interfaces:
type Provider interface {
Generate(ctx context.Context, req *Request) (*Result, error)
}
type Storage interface {
Upload(ctx context.Context, result *Result) (*StorageResult, error)
}Client.GenerateAndStore calls them in sequence, wrapping errors at each step.
provider := imagen.NewOpenAIProvider("sk-...")Supports gpt-image-2, dall-e-3, and dall-e-2. Configurable via options:
WithOpenAIModel— model nameWithOpenAISize— output dimensionsWithOpenAIQuality—standardorhdWithOpenAIStyle—vividornaturalWithOpenAIResponseFormat—urlorb64_jsonWithOpenAIHTTPClient— custom HTTP client
Handles b64_json and url response formats automatically, detects content type via magic bytes, and maps API errors to typed sentinels.
provider := imagen.NewStabilityProvider("...")Supports SDXL, SD3.5, and any Stability AI text-to-image model. Configurable via options:
WithStabilityEndpoint— API base URLWithStabilityModel— model ID (e.g.stable-diffusion-xl-1024-v1-0)WithStabilityCfgScale— classifier-free guidance scaleWithStabilitySteps— inference stepsWithStabilityStylePreset— style preset (photographic,digital-art,anime, etc.)WithStabilityOutputFormat— output format (png,webp,jpeg)WithStabilityHTTPClient— custom HTTP client
Size is parsed from Request.Size (e.g. "1024x1024"). Returns the seed from the first artifact and detects content type from magic bytes.
storage := imagen.NewGCSStorage("my-bucket")Creates Firebase Storage-compatible download URLs by default. Customizable via options:
WithGCSObjectNamer— custom path generation functionWithGCSPublicURL— custom URL builder
Also provides:
UploadReader— for streaming image data from a readerEnsureFirebaseToken— retrieve or create Firebase download tokens for existing objects
Authentication: Uses Application Default Credentials. For local dev:
gcloud auth application-default loginFor production (Cloud Run, GCE, GKE), the default service account is used automatically.
All provider and storage errors are wrapped with fmt.Errorf("...: %w", err), making them inspectable with errors.Is. Sentinel errors:
var (
ErrAPIKeyRequired // API key is required
ErrGCSBucketRequired // GCS bucket is required
ErrNoImageData // no image data returned
ErrEmptyURL // empty image URL
ErrContentFiltered // content filtered by provider policy
ErrRateLimited // rate limited by provider
ErrUploadFailed // upload to storage failed
ErrInvalidSize // invalid image size format
ErrEmptyPrompt // prompt is required
)Example:
result, err := client.GenerateAndStore(ctx, req)
if errors.Is(err, imagen.ErrContentFiltered) {
log.Println("Prompt was filtered by safety policy")
}The built-in generic retry utility is available for any operation:
result, err := imagen.RetryDo(ctx, imagen.RetryConfig{
MaxRetries: 3,
BaseDelay: 1 * time.Second,
MaxDelay: 30 * time.Second,
OperationLabel: "my_operation",
}, func(ctx context.Context) (string, error) {
return myFlakyOperation(ctx)
})Features exponential backoff with jitter, context cancellation, and configurable ShouldRetry predicate.
Full working examples are in the examples/ directory:
basic— minimal end-to-end generation and upload
Run any example with:
cd examples/basic
cp .env.example .env # fill in your credentials
go run .imagen/
├── imagen.go — Core types, interfaces, Client orchestrator
├── openai.go — OpenAI provider implementation
├── stability.go — Stability AI provider implementation
├── gcs.go — GCS storage implementation
├── config.go — Config, options, env loading
├── errors.go — Sentinel errors
├── retry.go — Generic retry utility
├── retry_test.go — Retry tests
├── examples/ — Runnable examples
├── Makefile — Build, test, lint targets
└── .env.example — Environment variable template
make test # run tests
make test-race # run with race detector
make lint # run golangci-lint
make build # compile all packagesMIT — see LICENSE.
Mayank Rana — built for reusable, production-grade AI image pipelines.