A framework-agnostic Go module for generating RSS and Atom feeds. Inspired by php-feed, this package works seamlessly with any Go web framework including Gin, Echo, Fiber, Chi, and standard net/http.
- Framework-agnostic: Use with Gin, Echo, Fiber, Chi, or standard net/http (adapters available separately)
- Multiple formats: RSS 2.0 and Atom 1.0 support
- Rich content: Support for images, enclosures, categories, and custom elements
- Modern Go: Type-safe, extensible, and robust (Go 1.22+)
- High test coverage: Comprehensive test suite with CI/CD integration
- Easy integration: Simple API, drop-in for handlers/middleware
- Extensible: Adapters for popular Go web frameworks
- Production ready: Used in production environments
- π Installation
- π Usage Examples
- π§ Framework Adapters
- οΏ½ Working Examples
- π Documentation Wiki
- π§ͺ Testing & Development
- π€ Contributing
- π Security Policy
- π Support & Funding
- π License
go get go.rumenx.com/feed
Each framework adapter is a separate module. Install only what you need:
# For Gin
go get go.rumenx.com/feed/adapters/gin
# For Echo
go get go.rumenx.com/feed/adapters/echo
# For Fiber
go get go.rumenx.com/feed/adapters/fiber
# For Chi
go get go.rumenx.com/feed/adapters/chi
package main
import (
"net/http"
"time"
"go.rumenx.com/feed"
)
func feedHandler(w http.ResponseWriter, r *http.Request) {
f := feed.New()
// Set feed metadata
f.SetTitle("My Blog Feed")
f.SetDescription("Latest posts from my blog")
f.SetLink("https://example.com")
f.SetLanguage("en-us")
// Add feed items
f.AddItem(feed.Item{
Title: "First Post",
Description: "This is my first blog post",
Link: "https://example.com/posts/first-post",
Author: "Rumen Damyanov",
PubDate: time.Now(),
GUID: "https://example.com/posts/first-post",
})
// Render as RSS
w.Header().Set("Content-Type", "application/xml")
rss, err := f.RSS()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Write(rss)
}
func main() {
http.HandleFunc("/feed.xml", feedHandler)
http.ListenAndServe(":8080", nil)
}
f := feed.New()
// Set comprehensive feed metadata
f.SetTitle("My News Site")
f.SetDescription("Latest news and updates")
f.SetLink("https://example.com")
f.SetLanguage("en-us")
f.SetCopyright("Β© 2025 Example News")
f.SetManagingEditor("editor@example.com (News Editor)")
f.SetWebmaster("webmaster@example.com (Web Master)")
f.SetTTL(60) // Cache for 60 minutes
// Add item with rich content
f.AddItem(feed.Item{
Title: "Breaking News",
Description: "Important news update with media",
Link: "https://example.com/news/breaking",
Author: "reporter@example.com (News Reporter)",
PubDate: time.Now(),
GUID: "https://example.com/news/breaking",
Categories: []string{"news", "breaking", "politics"},
Enclosure: &feed.Enclosure{
URL: "https://example.com/audio/news.mp3",
Length: "1048576",
Type: "audio/mpeg",
},
Images: []feed.Image{
{
URL: "https://example.com/images/news.jpg",
Title: "Breaking News Image",
Link: "https://example.com/news/breaking",
},
},
})
// Multiple output formats
rssData, _ := f.RSS() // RSS 2.0
atomData, _ := f.Atom() // Atom 1.0
Framework adapters are separate modules to keep the core library dependency-free. Install only the adapters you need.
package main
import (
"github.com/gin-gonic/gin"
"go.rumenx.com/feed/adapters/gin"
)
func main() {
r := gin.Default()
r.GET("/feed.xml", ginadapter.Feed(func() *feed.Feed {
f := feed.New()
f.SetTitle("My Site")
f.AddItem(feed.Item{
Title: "Hello World",
Link: "https://example.com/hello",
})
return f
}))
r.Run(":8080")
}
package main
import (
"github.com/gofiber/fiber/v2"
"go.rumenx.com/feed/adapters/fiber"
)
func main() {
app := fiber.New()
app.Get("/feed.xml", fiberadapter.Feed(func() *feed.Feed {
f := feed.New()
f.SetTitle("My Site")
f.AddItem(feed.Item{
Title: "Hello World",
Link: "https://example.com/hello",
})
return f
}))
app.Listen(":8080")
}
package main
import (
"github.com/labstack/echo/v4"
"go.rumenx.com/feed/adapters/echo"
)
func main() {
e := echo.New()
e.GET("/feed.xml", echoadapter.Feed(func() *feed.Feed {
f := feed.New()
f.SetTitle("My Site")
f.AddItem(feed.Item{
Title: "Hello World",
Link: "https://example.com/hello",
})
return f
}))
e.Start(":8080")
}
package main
import (
"net/http"
"github.com/go-chi/chi/v5"
"go.rumenx.com/feed/adapters/chi"
)
func main() {
r := chi.NewRouter()
r.Get("/feed.xml", chiadapter.Feed(func() *feed.Feed {
f := feed.New()
f.SetTitle("My Site")
f.AddItem(feed.Item{
Title: "Hello World",
Link: "https://example.com/hello",
})
return f
}))
http.ListenAndServe(":8080", r)
}
You can add feed items using either the Add()
or AddItem()
methods:
Add() β Simple, parameter-based:
// Recommended for simple use cases
f.Add(
"Hello World", // title
"This is a hello world post", // description
"https://example.com/hello", // link
"author@example.com", // author
time.Now(), // pubDate
)
AddItem() β Advanced, struct-based:
// Add a single item with a struct
f.AddItem(feed.Item{
Title: "Hello World",
Description: "This is a hello world post",
Link: "https://example.com/hello",
Author: "author@example.com",
PubDate: time.Now(),
Categories: []string{"general", "blog"},
})
// Add multiple items at once (batch add)
f.AddItems([]feed.Item{
{Title: "Post 1", Link: "https://example.com/post1"},
{Title: "Post 2", Link: "https://example.com/post2"},
})
The examples/
directory contains complete, runnable applications:
Located in examples/frameworks/
, each with its own module:
Framework | Port | Run Command | Features |
---|---|---|---|
Gin | :8080 |
cd examples/frameworks/gin && go run main.go |
Clean API, middleware support |
Echo | :8081 |
cd examples/frameworks/echo && go run main.go |
Performance-focused, middleware ecosystem |
Fiber | :8082 |
cd examples/frameworks/fiber && go run main.go |
Express-inspired, fast HTTP engine |
Chi | :8083 |
cd examples/frameworks/chi && go run main.go |
Lightweight router, auto-detection middleware |
examples/basic/
- Simple RSS/Atom generationexamples/complete/
- Advanced features demonstration
Each example includes:
- π‘ RSS 2.0 feeds (
/feed.xml
) - βοΈ Atom 1.0 feeds (
/atom.xml
) - π Multi-format endpoints (
/feed?format=rss|atom
) - π Interactive HTML browsers
- π― Framework-specific features
For comprehensive documentation and examples:
- π Quick Start Guide - Get up and running quickly
- π§ Basic Usage - Core functionality and examples
- π Advanced Usage - Advanced features and customization
- π Framework Integration - Integration with popular frameworks
- π― Best Practices - Performance tips and recommendations
- π€ Contributing Guidelines - How to contribute to this project
- π Security Policy - Security guidelines and vulnerability reporting
- π Funding & Support - Support and sponsorship information
# Run all tests
go test ./...
# Run tests with coverage
go test -cover ./...
# Generate HTML coverage report
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out -o coverage.html
# Run static analysis
go vet ./...
# Format code
go fmt ./...
# Run linter (if installed)
golangci-lint run
We welcome contributions! Please see our Contributing Guidelines for details on:
- Development setup
- Coding standards
- Testing requirements
- Pull request process
If you discover a security vulnerability, please review our Security Policy for responsible disclosure guidelines.
If you find this package helpful, consider:
- β Starring the repository
- π Supporting development
- π Reporting issues
- π€ Contributing improvements