forge

package module
v0.3.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 17, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

README

Forge

CI Go Reference Go Report Card License

A simple, opinionated Go framework for building micro-SaaS applications.

Forge is designed around the principle of "no magic" — it uses explicit, readable code with no reflection or service containers. The framework provides a thin orchestration layer while keeping business logic in plain Go handlers.

Installation

go get github.com/dmitrymomot/forge

Quick Start

package main

import (
    "log"
    "github.com/dmitrymomot/forge"
)

func main() {
    app := forge.New(
        forge.AppConfig{},
        forge.WithHandlers(&MyHandler{}),
    )

    if err := forge.Run(
        forge.RunConfig{Address: ":8080"},
        forge.WithFallback(app),
    ); err != nil {
        log.Fatal(err)
    }
}

type MyHandler struct{}

func (h *MyHandler) Routes(r forge.Router) {
    r.GET("/", h.index)
}

func (h *MyHandler) index(c forge.Context) error {
    return c.JSON(200, map[string]string{"message": "Hello, World!"})
}

Core Concepts

Handlers

Handlers implement the Handler interface to declare routes:

type AuthHandler struct {
    repo *repository.Queries
}

func NewAuth(repo *repository.Queries) *AuthHandler {
    return &AuthHandler{repo: repo}
}

func (h *AuthHandler) Routes(r forge.Router) {
    r.GET("/login", h.showLogin)
    r.POST("/login", h.handleLogin)
    r.POST("/logout", h.handleLogout)
}

func (h *AuthHandler) showLogin(c forge.Context) error {
    return c.Render(http.StatusOK, views.LoginPage())
}
Context

The Context interface embeds context.Context, so it can be passed directly to any function expecting a standard library context. It also provides built-in helpers for common tasks:

func (h *Handler) getUser(c forge.Context) error {
    // c satisfies context.Context — pass it to DB calls, HTTP clients, etc.
    user, err := h.repo.GetUser(c, c.UserID())
    if err != nil {
        return err
    }
    return c.JSON(200, user)
}

Context carries everything you need for a request — logging, cookies, flash messages, domain info:

func (h *Handler) updateSettings(c forge.Context) error {
    c.LogInfo("updating settings", "user", c.UserID(), "domain", c.Domain())

    // Flash messages for post-redirect-get
    c.SetFlash("success", "Settings saved!")
    return c.Redirect(http.StatusSeeOther, "/settings")
}

func (h *Handler) showSettings(c forge.Context) error {
    var msg string
    c.Flash("success", &msg) // reads and deletes flash

    return c.Render(http.StatusOK, views.Settings(msg))
}
Type-Safe Parameters

Generic helpers provide type-safe access to URL and query parameters:

func (h *Handler) listItems(c forge.Context) error {
    page := forge.QueryDefault[int](c, "page", 1)
    limit := forge.QueryDefault[int](c, "limit", 20)
    id := forge.Param[int64](c, "id")

    items, err := h.repo.ListItems(c, page, limit)
    if err != nil {
        return err
    }
    return c.JSON(http.StatusOK, items)
}

Supported types: ~string, ~int, ~int64, ~float64, ~bool.

Data Binding & Validation

Bind request data into structs with automatic sanitization and validation:

type CreateContact struct {
    Name  string `form:"name"  validate:"required;max:100"`
    Email string `form:"email" validate:"required;email"`
    Phone string `form:"phone" sanitize:"trim;numeric"`
}

func (h *Handler) createContact(c forge.Context) error {
    var req CreateContact
    if errs, err := c.Bind(&req); err != nil {
        return err
    } else if errs != nil {
        return c.Render(http.StatusUnprocessableEntity, views.Form(errs))
    }
    // req is sanitized and validated
    return h.repo.CreateContact(c, req.Name, req.Email, req.Phone)
}

Also available: c.BindJSON() for API endpoints and c.BindQuery() for query parameters.

Sessions & Authentication

Enable server-side session management with automatic creation:

app := forge.New(
    forge.AppConfig{},
    forge.WithSession(postgresStore,
        forge.WithSessionTTL(7 * 24 * time.Hour),
        forge.WithMaxSessionsPerUser(3),
        forge.WithSessionFingerprint(
            forge.FingerprintCookie,
            forge.FingerprintWarn,
        ),
    ),
)

Authenticate users with AuthenticateSession — it sets the user ID, rotates the session token, and marks the session as authenticated in one call:

func (h *Handler) login(c forge.Context) error {
    // ...validate credentials...
    if err := c.AuthenticateSession(user.ID); err != nil {
        return err
    }
    return c.Redirect(http.StatusSeeOther, "/dashboard")
}

Then use the built-in identity methods — no need to manually read session keys:

func (h *Handler) dashboard(c forge.Context) error {
    if !c.IsAuthenticated() {
        return c.Redirect(http.StatusSeeOther, "/login")
    }

    // c.UserID() returns the authenticated user's ID
    user, err := h.repo.GetUser(c, c.UserID())
    if err != nil {
        return err
    }

    canEdit := c.IsCurrentUser(user.ID)
    return c.Render(http.StatusOK, views.Dashboard(user, canEdit))
}

For custom session data, use SessionGet and SessionSet:

forge.SessionSet(c, "theme", "dark")
theme, ok := forge.SessionGet[string](c, "theme")

Session management:

c.DestroySession()                // Logout current device
c.DestroyOtherSessions()          // Logout all other devices
c.DestroyAllSessions(c.UserID())  // Logout everywhere
sessions, _ := c.ListSessions(c.UserID()) // Show active sessions
RBAC

Configure role-based access control:

app := forge.New(
    forge.AppConfig{},
    forge.WithRoles(
        forge.RolePermissions{
            "admin":  {"users.read", "users.write", "billing.manage"},
            "member": {"users.read"},
        },
        func(c forge.Context) string {
            return forge.ContextValue[string](c, roleKey{})
        },
    ),
)

Check permissions in handlers:

func (h *Handler) deleteUser(c forge.Context) error {
    if !c.Can("users.write") {
        return forge.ErrForbidden("You do not have permission")
    }
    return h.repo.DeleteUser(c, forge.Param[string](c, "id"))
}

func (h *Handler) adminPanel(c forge.Context) error {
    c.LogInfo("admin access", "role", c.Role(), "user", c.UserID())
    return c.Render(http.StatusOK, views.Admin())
}
Background Jobs

Enable background job processing with River:

app := forge.New(
    forge.AppConfig{},
    forge.WithJobs(pgxPool,
        job.Config{Workers: 2},
        job.WithTask(EmailTask{}),
        job.WithScheduledTask(CleanupTask{}),
    ),
)

Define tasks using structural typing:

type EmailTask struct{}

func (EmailTask) Name() string { return "send_email" }

func (EmailTask) Handle(ctx context.Context, p struct{ Email string }) error {
    // Send email...
    return nil
}

Enqueue jobs from handlers:

func (h *Handler) signup(c forge.Context) error {
    err := c.Enqueue("send_email",
        struct{ Email string }{Email: user.Email},
        job.WithQueue("emails"),
        job.WithScheduledIn(1*time.Minute),
    )
    if err != nil {
        return err
    }
    return c.Redirect(http.StatusSeeOther, "/signup/confirm")
}
File Storage

Enable S3-compatible file storage:

s, err := storage.New(storage.Config{
    Endpoint:  "s3.amazonaws.com",
    AccessKey: os.Getenv("AWS_ACCESS_KEY_ID"),
    SecretKey: os.Getenv("AWS_SECRET_ACCESS_KEY"),
    Bucket:    "myapp-uploads",
    Region:    "us-east-1",
})
if err != nil {
    log.Fatal(err)
}

app := forge.New(
    forge.AppConfig{},
    forge.WithStorage(s),
)

Upload, download, and manage files directly from handlers:

func (h *Handler) uploadAvatar(c forge.Context) error {
    info, err := c.Upload("avatar",
        storage.WithPrefix("avatars"),
        storage.WithTenant(c.UserID()),
        storage.WithValidation(
            storage.MaxSize(5*1024*1024),
            storage.ImageOnly(),
        ),
    )
    if err != nil {
        return err
    }
    // Save info.Key to database, generate URLs later
    return c.JSON(http.StatusOK, map[string]string{"key": info.Key})
}

func (h *Handler) getAvatarURL(c forge.Context) error {
    url, err := c.FileURL(avatarKey, storage.WithExpiry(1*time.Hour))
    if err != nil {
        return err
    }
    return c.JSON(http.StatusOK, map[string]string{"url": url})
}
HTMX-Aware Rendering

Context automatically detects HTMX requests and renders accordingly:

func (h *Handler) contacts(c forge.Context) error {
    contacts, err := h.repo.ListContacts(c)
    if err != nil {
        return err
    }

    // HTMX request → renders just the partial
    // Regular request → renders the full page with layout
    return c.RenderPartial(http.StatusOK,
        views.ContactsPage(contacts), // full page
        views.ContactsList(contacts), // partial for HTMX
    )
}

Check HTMX state: c.IsHTMX() returns true for HTMX-initiated requests. Redirects automatically use HX-Redirect headers when appropriate.

Server-Sent Events

Stream events to clients using channels:

func (h *Handler) streamEvents(c forge.Context) error {
    ch := make(chan forge.SSEEvent)
    go func() {
        defer close(ch)
        for {
            select {
            case <-c.Done():
                return
            case event := <-eventChan:
                ch <- forge.SSEString("message", event.Data)
            }
        }
    }()
    return c.SSE(ch)
}
Error Handling

Return errors from handlers using convenience constructors or the context helper:

func (h *Handler) getUser(c forge.Context) error {
    id := forge.Param[string](c, "id")
    user, err := h.repo.GetUser(c, id)
    if err == sql.ErrNoRows {
        return forge.ErrNotFound("User not found")
    }
    if err != nil {
        // c.Error() creates an HTTPError with the given status and message
        return c.Error(500, "Failed to fetch user", forge.WithError(err))
    }
    return c.JSON(http.StatusOK, user)
}

Customize error handling globally:

app := forge.New(
    forge.AppConfig{},
    forge.WithErrorHandler(func(c forge.Context, err error) error {
        if httpErr := forge.AsHTTPError(err); httpErr != nil {
            return c.JSON(httpErr.StatusCode(), httpErr)
        }
        return c.JSON(http.StatusInternalServerError, map[string]string{
            "message": "Something went wrong",
        })
    }),
)

Built-In Middlewares

Import from github.com/dmitrymomot/forge/middlewares:

  • RequestID — Request tracking IDs
  • Recover — Panic recovery
  • I18n — Internationalization and localization
  • JWT — Token-based authentication
  • CSRF — Cross-site request forgery protection
  • RateLimit — Request rate limiting
  • AuditLog — Request and action logging
  • CORS — Cross-origin resource sharing
  • Auth — Authentication checks
  • RBAC — Role-based access control

Utility Packages

Available in github.com/dmitrymomot/forge/pkg:

  • binder — Request binding with validation
  • cache — Caching utilities
  • clientip — Client IP extraction
  • cookie — Secure cookie management
  • db — Database utilities
  • dnsverify — DNS verification helpers
  • fingerprint — Browser fingerprinting
  • geolocation — IP geolocation
  • hostrouter — Multi-domain routing
  • htmx — HTMX helpers
  • i18n — Internationalization
  • id — ID generation (ULID, ShortID)
  • job — Background job processing
  • jwt — JWT utilities
  • logger — Structured logging
  • mailer — Email sending
  • oauth — OAuth 2.0 helpers
  • qrcode — QR code generation
  • randomname — Random name generation
  • ratelimit — Rate limiting
  • redis — Redis utilities
  • sanitizer — HTML sanitization
  • secrets — Secrets management
  • slug — URL slug generation
  • storage — File storage
  • token — Token generation
  • totp — TOTP/2FA
  • useragent — User agent parsing
  • validator — Input validation
  • webhook — Webhook utilities

Configuration

Load environment variables into structs:

type Config struct {
    DatabaseURL string `env:"DATABASE_URL,required"`
    Port        string `env:"PORT" envDefault:":8080"`
    Debug       bool   `env:"DEBUG"`
}

var cfg Config
if err := forge.LoadConfig(&cfg); err != nil {
    log.Fatal(err)
}

Multi-Domain Routing

Compose multiple apps with host-based routing:

api := forge.New(
    forge.AppConfig{BaseDomain: "acme.com"},
    forge.WithHandlers(handlers.NewAPIHandler()),
)

website := forge.New(
    forge.AppConfig{BaseDomain: "acme.com"},
    forge.WithHandlers(handlers.NewLandingHandler()),
)

if err := forge.Run(
    forge.RunConfig{Address: ":8080"},
    forge.WithDomain("api.acme.com", api),
    forge.WithDomain("*.acme.com", website),
); err != nil {
    log.Fatal(err)
}

Commands

just test             # Tests with race detection + coverage
just bench            # Benchmarks with memory stats
just lint             # vet, golangci-lint, nilaway, betteralign, modernize
just fmt              # Format + organize imports
just test-integration # Docker-based integration tests

Claude Code Plugin

forge-skills is a Claude Code plugin that accelerates Forge development with three skills:

  • /forge-init <app-name> — Scaffold a complete project (config, Docker, env, task runner) with selectable subsystems (Postgres, Redis, sessions, jobs, storage, templ, HTMX, Tailwind, mailer, OAuth)
  • /forge-build <feature> — Generate handlers, DB migrations + sqlc queries, background jobs, auth flows, email templates, storage integration, SSE endpoints, and templ views
  • /templui <description> — Generate Go templ templates using the templui component library (41 components, Tailwind + HTMX-ready)

Install inside Claude Code (v1.0.33+):

/plugin marketplace add dmitrymomot/forge-skills
/plugin install forge-skills@forge-skills

Documentation

Full API documentation is available via:

go doc -all github.com/dmitrymomot/forge

Or online at pkg.go.dev/github.com/dmitrymomot/forge

Contributing

See CONTRIBUTING.md for guidelines.

Design Principles

  • No reflection, no service containers, no magic
  • Packages receive values via parameters, not context
  • Public methods must not return unexported types
  • Framework provides utility packages; business logic belongs in consumer repos
  • All IDs generated using pkg/id/ package exclusively

License

Apache 2.0 — see LICENSE for details.

Documentation

Overview

Package forge provides a simple, opinionated framework for building B2B micro-SaaS applications in Go.

Forge is designed around the principle of "no magic" — it uses explicit, readable code with no reflection or service containers. The framework provides a thin orchestration layer while keeping business logic in plain Go handlers.

Quick Start

Create a new application with New(), configure it with options, and pass it to Run():

app := forge.New(
    forge.AppConfig{},
    forge.WithHandlers(
        handlers.NewAuth(repo),
        handlers.NewPages(repo),
    ),
)

if err := forge.Run(
    forge.RunConfig{},
    forge.WithFallback(app),
    forge.WithRunLogger(logger),
); err != nil {
    log.Fatal(err)
}

Context as context.Context

The Context interface embeds context.Context, so it can be passed directly to any function that expects a standard library context:

func (h *Handler) getUser(c forge.Context) error {
    // c satisfies context.Context — pass it to DB calls, HTTP clients, etc.
    user, err := h.repo.GetUser(c, userID)
    if err != nil {
        return err
    }
    return c.JSON(200, user)
}

Identity and Authentication

Context provides convenience methods for checking the current user. These are shortcuts over the session system and return safe defaults when no session is configured:

func (h *Handler) showProfile(c forge.Context) error {
    if !c.IsAuthenticated() {
        return c.Redirect(http.StatusSeeOther, "/login")
    }

    user, err := h.repo.GetUser(c, c.UserID())
    if err != nil {
        return err
    }

    // Only allow users to edit their own profile
    canEdit := c.IsCurrentUser(user.ID)
    return c.Render(http.StatusOK, views.Profile(user, canEdit))
}

Sessions

Enable server-side session management with WithSession. Sessions auto-create on first access via SessionGet or SessionSet:

app := forge.New(
    forge.AppConfig{},
    forge.WithSession(postgresStore,
        forge.WithSessionTTL(7 * 24 * time.Hour),
        forge.WithMaxSessionsPerUser(3),
        forge.WithSessionFingerprint(
            forge.FingerprintCookie,
            forge.FingerprintWarn,
        ),
    ),
)

Use SessionGet and SessionSet for type-safe access:

func (h *Handler) login(c forge.Context) error {
    if err := forge.SessionSet(c, "user_id", user.ID); err != nil {
        return err
    }
    if err := forge.SessionSet(c, "login_time", time.Now()); err != nil {
        return err
    }
    return c.Redirect(http.StatusSeeOther, "/dashboard")
}

func (h *Handler) dashboard(c forge.Context) error {
    userID, ok := forge.SessionGet[string](c, "user_id")
    if !ok {
        return c.Redirect(http.StatusSeeOther, "/login")
    }
    // Use userID...
    return c.Render(http.StatusOK, views.Dashboard())
}

Role-Based Access Control (RBAC)

Configure permissions with WithRoles. The role extractor is called lazily on the first [Context.Can] call and cached for the request:

app := forge.New(
    forge.AppConfig{},
    forge.WithRoles(
        forge.RolePermissions{
            "admin":  {"users.read", "users.write", "billing.manage"},
            "member": {"users.read"},
        },
        func(c forge.Context) string {
            return forge.ContextValue[string](c, roleKey{})
        },
    ),
)

Check permissions in handlers:

func (h *Handler) deleteUser(c forge.Context) error {
    if !c.Can("users.write") {
        return forge.ErrForbidden("You do not have permission")
    }
    return h.repo.DeleteUser(c, forge.Param[string](c, "id"))
}

Type-Safe Parameter Helpers

Generic helper functions provide type-safe access to URL and query parameters. They use strconv for conversion and return zero values on parse failure:

func (h *Handler) listItems(c forge.Context) error {
    page := forge.QueryDefault[int](c, "page", 1)
    limit := forge.QueryDefault[int](c, "limit", 20)
    items, err := h.repo.ListItems(c, page, limit)
    if err != nil {
        return err
    }
    return c.JSON(http.StatusOK, items)
}

func (h *Handler) getItem(c forge.Context) error {
    id := forge.Param[int64](c, "id")
    item, err := h.repo.GetItem(c, id)
    if err != nil {
        return err
    }
    return c.JSON(http.StatusOK, item)
}

Supported types: ~string, ~int, ~int64, ~float64, ~bool.

Handlers

Handlers implement the Handler interface to declare routes:

type AuthHandler struct {
    repo *repository.Queries
}

func NewAuth(repo *repository.Queries) *AuthHandler {
    return &AuthHandler{repo: repo}
}

func (h *AuthHandler) Routes(r forge.Router) {
    r.GET("/login", h.showLogin)
    r.POST("/login", h.handleLogin)
    r.POST("/logout", h.handleLogout)
}

func (h *AuthHandler) showLogin(c forge.Context) error {
    return c.Render(http.StatusOK, views.LoginPage())
}

Middleware

Middleware wraps handlers to add cross-cutting concerns:

func RequestLogger(log *slog.Logger) forge.Middleware {
    return func(next forge.HandlerFunc) forge.HandlerFunc {
        return func(c forge.Context) error {
            start := time.Now()
            err := next(c)
            log.Info("request",
                "method", c.Request().Method,
                "path", c.Request().URL.Path,
                "duration", time.Since(start),
                "error", err,
            )
            return err
        }
    }
}

Add middleware globally with WithMiddleware:

app := forge.New(
    forge.AppConfig{},
    forge.WithMiddleware(
        RequestLogger(logger),
        middlewares.RequestID(middlewares.RequestIDConfig{}),
        middlewares.Recover(middlewares.RecoverConfig{}),
    ),
)

Built-In Middlewares

The middlewares package provides common functionality:

  • RequestID: Adds request tracking IDs
  • Recover: Handles panics gracefully
  • I18n: Internationalization and localization
  • JWT: Token-based authentication
  • CSRF: Cross-site request forgery protection
  • RateLimit: Request rate limiting
  • AuditLog: Request and action logging

Jobs and Background Processing

Enable background job processing with River integration:

app := forge.New(
    forge.AppConfig{},
    forge.WithJobs(pgxPool,
        job.Config{
            Workers: 2,
        },
        job.WithTask(EmailTask{}),
        job.WithScheduledTask(CleanupTask{}),
    ),
)

Define tasks using structural typing:

type EmailTask struct{}

func (EmailTask) Name() string { return "send_email" }
func (EmailTask) Handle(ctx context.Context, p struct{ Email string }) error {
    // Send email...
    return nil
}

Enqueue jobs from handlers:

func (h *Handler) signup(c forge.Context) error {
    // ...validation...
    err := c.Enqueue("send_email",
        struct{ Email string }{Email: user.Email},
        job.WithQueue("emails"),
        job.WithScheduledIn(1*time.Minute),
    )
    if err != nil {
        return err
    }
    return c.Redirect(http.StatusSeeOther, "/signup/confirm")
}

File Storage

Enable S3-compatible file storage:

s, err := storage.New(storage.Config{
    Endpoint:  "s3.amazonaws.com",
    AccessKey: os.Getenv("AWS_ACCESS_KEY_ID"),
    SecretKey: os.Getenv("AWS_SECRET_ACCESS_KEY"),
    Bucket:    "myapp-uploads",
    Region:    "us-east-1",
})
if err != nil {
    log.Fatal(err)
}

app := forge.New(
    forge.AppConfig{},
    forge.WithStorage(s),
)

Upload and download files from handlers:

func (h *Handler) uploadAvatar(c forge.Context) error {
    info, err := c.Upload("avatar",
        storage.WithPrefix("avatars"),
        storage.WithValidation(
            storage.MaxSize(5*1024*1024),
            storage.ImageOnly(),
        ),
    )
    if err != nil {
        return err
    }

    // Save info.Key to database
    return c.JSON(http.StatusOK, map[string]string{
        "url": info.URL,
    })
}

Server-Sent Events (SSE)

Stream events to clients using the channel-based SSE API. The framework handles headers, keepalive, and flushing:

func (h *Handler) streamEvents(c forge.Context) error {
    ch := make(chan forge.SSEEvent)
    go func() {
        defer close(ch)
        for {
            select {
            case <-c.Done():
                return
            case event := <-eventChan:
                ch <- forge.SSEString("message", event.Data)
            }
        }
    }()
    return c.SSE(ch)
}

Multi-Domain Routing

For applications that need host-based routing, compose multiple Apps with Run():

api := forge.New(
    forge.AppConfig{BaseDomain: "acme.com"},
    forge.WithHandlers(handlers.NewAPIHandler()),
)

website := forge.New(
    forge.AppConfig{BaseDomain: "acme.com"},
    forge.WithHandlers(handlers.NewLandingHandler()),
)

if err := forge.Run(
    forge.RunConfig{Address: ":8080"},
    forge.WithDomain("api.acme.com", api),
    forge.WithDomain("*.acme.com", website),
    forge.WithRunLogger(logger),
); err != nil {
    log.Fatal(err)
}

Error Handling

Return HTTPError from handlers to set the status code and error details:

func (h *Handler) getUser(c forge.Context) error {
    user, err := h.repo.GetUser(c, id)
    if err == sql.ErrNoRows {
        return forge.ErrNotFound("User not found")
    }
    if err != nil {
        return forge.ErrInternal("Failed to fetch user")
    }
    return c.JSON(http.StatusOK, user)
}

Customize error response handling with WithErrorHandler:

app := forge.New(
    forge.AppConfig{},
    forge.WithErrorHandler(func(c forge.Context, err error) error {
        if httpErr := forge.AsHTTPError(err); httpErr != nil {
            return c.JSON(httpErr.StatusCode(), httpErr)
        }
        return c.JSON(http.StatusInternalServerError, map[string]string{
            "message": "Something went wrong",
        })
    }),
)

Shutdown

The application handles SIGINT/SIGTERM for graceful shutdown. Register cleanup functions with WithShutdownHook:

if err := forge.Run(
    forge.RunConfig{Address: ":8080"},
    forge.WithFallback(app),
    forge.WithShutdownHook(func(ctx context.Context) error {
        return pool.Close()
    }),
); err != nil {
    log.Fatal(err)
}

Configuration

Load configuration from environment variables with LoadConfig:

type Config struct {
    DatabaseURL string `env:"DATABASE_URL,required"`
    Port        string `env:"PORT" envDefault:":8080"`
    Debug       bool   `env:"DEBUG"`
}

var cfg Config
if err := forge.LoadConfig(&cfg); err != nil {
    log.Fatal(err)
}

Testing

For testing, use httptest.NewServer with the app:

app := forge.New(
    forge.AppConfig{},
    forge.WithHandlers(myHandler),
)
ts := httptest.NewServer(app.Router())
defer ts.Close()

resp, err := http.Get(ts.URL + "/path")
if err != nil {
    t.Fatal(err)
}
// Assert response...

Index

Constants

View Source
const (
	// FingerprintDisabled disables fingerprint generation and validation.
	FingerprintDisabled = internal.FingerprintDisabled
	// FingerprintCookie uses default settings, excludes IP. Best for most web apps.
	FingerprintCookie = internal.FingerprintCookie
	// FingerprintJWT uses minimal fingerprint, excludes Accept headers.
	FingerprintJWT = internal.FingerprintJWT
	// FingerprintHTMX uses only User-Agent, avoids HTMX header variations.
	FingerprintHTMX = internal.FingerprintHTMX
	// FingerprintStrict includes IP address. WARNING: causes false positives.
	FingerprintStrict = internal.FingerprintStrict
)

Fingerprint mode constants.

View Source
const (
	// FingerprintWarn logs a warning but allows the session to continue.
	FingerprintWarn = internal.FingerprintWarn
	// FingerprintReject invalidates the session on fingerprint mismatch.
	FingerprintReject = internal.FingerprintReject
)

Fingerprint strictness constants.

Variables

View Source
var (
	ErrCookieNotFound  = cookie.ErrNotFound
	ErrCookieNoSecret  = cookie.ErrNoSecret
	ErrCookieBadSecret = cookie.ErrBadSecret
	ErrCookieBadSig    = cookie.ErrBadSig
	ErrCookieDecrypt   = cookie.ErrDecrypt
)

Cookie errors for checking return values.

View Source
var (
	ErrSessionNotConfigured       = internal.ErrSessionNotConfigured
	ErrSessionNotFound            = internal.ErrSessionNotFound
	ErrSessionExpired             = internal.ErrSessionExpired
	ErrSessionInvalidToken        = internal.ErrSessionInvalidToken
	ErrSessionFingerprintMismatch = internal.ErrSessionFingerprintMismatch
)

Session errors for checking return values.

View Source
var (
	// SSEString creates a string SSE event.
	SSEString = internal.SSEString
	// SSEJSON creates a JSON SSE event.
	SSEJSON = internal.SSEJSON
	// SSETempl creates an HTML SSE event from a templ Component.
	SSETempl = internal.SSETempl
	// SSEComment creates an SSE comment (keepalive, etc.).
	SSEComment = internal.SSEComment
	// SSERetry creates an SSE retry directive.
	SSERetry = internal.SSERetry
)

SSE event constructors

View Source
var (
	WithSessionTTL            = internal.WithSessionTTL
	WithMaxSessionsPerUser    = internal.WithMaxSessionsPerUser
	WithSessionTouchThreshold = internal.WithSessionTouchThreshold
	WithSessionCookieName     = internal.WithSessionCookieName
	WithSessionFingerprint    = internal.WithSessionFingerprint
	WithSessionLogger         = internal.WithSessionLogger
)

Session option re-exports

View Source
var (
	ErrJobNotConfigured     = job.ErrNotConfigured
	ErrJobUnknownTask       = job.ErrUnknownTask
	ErrJobInvalidPayload    = job.ErrInvalidPayload
	ErrJobHealthcheckFailed = job.ErrHealthcheckFailed
	ErrJobPoolRequired      = job.ErrPoolRequired
)

Job errors for checking return values.

View Source
var (
	ErrStorageNotConfigured  = storage.ErrNotConfigured
	ErrStorageInvalidConfig  = storage.ErrInvalidConfig
	ErrStorageEmptyFile      = storage.ErrEmptyFile
	ErrStorageFileTooLarge   = storage.ErrFileTooLarge
	ErrStorageFileTooSmall   = storage.ErrFileTooSmall
	ErrStorageInvalidMIME    = storage.ErrInvalidMIME
	ErrStorageNotFound       = storage.ErrNotFound
	ErrStorageAccessDenied   = storage.ErrAccessDenied
	ErrStorageUploadFailed   = storage.ErrUploadFailed
	ErrStorageDeleteFailed   = storage.ErrDeleteFailed
	ErrStoragePresignFailed  = storage.ErrPresignFailed
	ErrStorageInvalidURL     = storage.ErrInvalidURL
	ErrStorageDownloadFailed = storage.ErrDownloadFailed
)

Storage errors for checking return values.

View Source
var (
	WithCSRFTokenGenerator = middlewares.WithCSRFTokenGenerator
	WithCSRFErrorHandler   = middlewares.WithCSRFErrorHandler
	WithCSRFSkipFunc       = middlewares.WithCSRFSkipFunc
)

CSRF option constructor re-exports

View Source
var (
	WithRateLimitKeyFunc      = middlewares.WithRateLimitKeyFunc
	WithRateLimitErrorHandler = middlewares.WithRateLimitErrorHandler
	WithRateLimitSkipFunc     = middlewares.WithRateLimitSkipFunc
)

Rate limit option constructor re-exports

View Source
var (
	WithAuditLogger       = middlewares.WithAuditLogger
	WithAuditSkipFunc     = middlewares.WithAuditSkipFunc
	WithAuditActionFunc   = middlewares.WithAuditActionFunc
	WithAuditResourceFunc = middlewares.WithAuditResourceFunc
	WithAuditMetadataFunc = middlewares.WithAuditMetadataFunc
	WithAuditTimeout      = middlewares.WithAuditTimeout
)

Audit option constructor re-exports

Functions

func ContextValue

func ContextValue[T any](c Context, key any) T

ContextValue retrieves a typed value from the context. Returns the zero value of T if the key is not found or type assertion fails.

func GetCSRFToken

func GetCSRFToken(c Context) string

GetCSRFToken extracts the CSRF token from the context. Returns an empty string if no token is set.

func GetJWTClaims

func GetJWTClaims[T any](c Context) *T

GetJWTClaims extracts parsed JWT claims from the context. Returns nil if the JWT middleware is not applied or the type doesn't match.

func GetLanguage

func GetLanguage(c Context) string

GetLanguage extracts the resolved language from the context. Returns an empty string if the I18n middleware is not used.

func GetRateLimitInfo

func GetRateLimitInfo(c Context) *ratelimit.Info

GetRateLimitInfo returns the rate limit info stored in the context by the RateLimit middleware. Returns nil if the middleware was not applied or the request was skipped.

func GetRequestID

func GetRequestID(c Context) string

GetRequestID extracts the request ID from the context. Returns an empty string if no request ID is set.

func GetTranslator

func GetTranslator(c Context) *i18n.Translator

GetTranslator extracts the Translator from the context. Returns nil if the I18n middleware is not used.

func IsHTTPError

func IsHTTPError(err error) bool

IsHTTPError returns true if the error is an HTTPError.

func IsPanicError

func IsPanicError(err error) bool

IsPanicError returns true if the error is a PanicError.

func LoadConfig

func LoadConfig(dst any) error

LoadConfig parses environment variables into dst using struct tags. It loads .env from the working directory automatically. Struct fields use `env:"KEY"`, `envDefault:"value"`, and `envSeparator:","` tags to declare their bindings.

func Param

func Param[T ~string | ~int | ~int64 | ~float64 | ~bool](c Context, name string) T

Param retrieves a typed URL parameter from the request. Uses strconv for type conversion. Returns the zero value of T on parse error.

func Query

func Query[T ~string | ~int | ~int64 | ~float64 | ~bool](c Context, name string) T

Query retrieves a typed query parameter from the request. Uses strconv for type conversion. Returns the zero value of T on parse error.

func QueryDefault

func QueryDefault[T ~string | ~int | ~int64 | ~float64 | ~bool](c Context, name string, defaultValue T) T

QueryDefault retrieves a typed query parameter with a default value. Returns defaultValue if the parameter is empty or cannot be parsed.

func RequestIDExtractor

func RequestIDExtractor() logger.ContextExtractor

RequestIDExtractor returns a ContextExtractor for use with WithLogger. Automatically adds "request_id" to all log entries.

func Run

func Run(cfg RunConfig, opts ...RunOption) error

Run starts a multi-domain HTTP server and blocks until shutdown. Use this for composing multiple Apps under different domain patterns.

func SessionGet

func SessionGet[T any](c Context, key string) (T, bool)

SessionGet retrieves a typed value from the session. Returns (value, true) if found and type matches, (zero, false) otherwise.

Example:

func Handler(c forge.Context) error {
    userID, ok := forge.SessionGet[string](c, "user_id")
    if !ok {
        return c.Redirect(http.StatusSeeOther, "/login")
    }
    // Use userID...
}

This automatically creates the session if it doesn't exist.

func SessionSet

func SessionSet[T any](c Context, key string, value T) error

SessionSet stores a typed value in the session.

Example:

func LoginHandler(c forge.Context) error {
    // After validating credentials...
    if err := forge.SessionSet(c, "user_id", user.ID); err != nil {
        return err
    }
    if err := forge.SessionSet(c, "login_time", time.Now()); err != nil {
        return err
    }
    return c.Redirect(http.StatusSeeOther, "/dashboard")
}

This automatically creates the session if it doesn't exist and marks it dirty for saving.

func SetAuditMetadata

func SetAuditMetadata(c Context, key, value string)

SetAuditMetadata adds a key-value pair to the audit entry metadata. No-op if the AuditLog middleware is not applied.

func T

func T(c Context, key string, placeholders ...i18n.M) string

T translates a key using the Translator stored in context by the I18n middleware. Returns the key itself if no translator is in context.

func Tn

func Tn(c Context, key string, n int, placeholders ...i18n.M) string

Tn translates a key with pluralization using the Translator stored in context. Returns the key itself if no translator is in context.

Types

type App

type App = internal.App

App orchestrates the application lifecycle. It manages HTTP routing, middleware, and graceful shutdown.

func New

func New(cfg AppConfig, opts ...Option) *App

New creates a new application with the given config and options. The App is immutable after creation.

type AppConfig

type AppConfig = internal.AppConfig

AppConfig holds externally configurable application settings.

type AuditEntry

type AuditEntry = middlewares.Entry

AuditEntry represents a single audit log record.

func GetAuditEntry

func GetAuditEntry(c Context) *AuditEntry

GetAuditEntry extracts the audit entry from the context. Returns nil if the AuditLog middleware is not applied.

type AuditOption

type AuditOption = middlewares.AuditOption

AuditOption configures the AuditLog middleware.

type AuditStore

type AuditStore = middlewares.Store

AuditStore defines the interface for persisting audit log entries.

type CSRFConfig

type CSRFConfig = middlewares.CSRFConfig

CSRFConfig configures the CSRF middleware.

type CSRFOption

type CSRFOption = middlewares.CSRFOption

CSRFOption configures runtime dependencies for the CSRF middleware.

type CheckFunc

type CheckFunc = internal.CheckFunc

CheckFunc is the standard health check function signature.

type Component

type Component = internal.Component

Component is the interface for renderable templates.

type Context

type Context = internal.Context

Context provides request/response access and helper methods.

type ErrorHandler

type ErrorHandler = internal.ErrorHandler

ErrorHandler handles errors returned from handlers.

type Extractor

type Extractor = internal.Extractor

Extractor tries multiple sources in order and returns the first match. Use with FromHeader, FromQuery, FromCookie, etc. to compose extraction chains.

func NewExtractor

func NewExtractor(sources ...ExtractorSource) Extractor

NewExtractor creates an Extractor that tries the given sources in order. Returns the first non-empty value found.

type ExtractorSource

type ExtractorSource = internal.ExtractorSource

ExtractorSource extracts a value from the request context. Returns the value and true if found, or ("", false) if not present.

func FromAcceptLanguage

func FromAcceptLanguage(available []string) ExtractorSource

FromAcceptLanguage returns an ExtractorSource that parses the Accept-Language header and matches against the available languages.

func FromBearerToken

func FromBearerToken() ExtractorSource

FromBearerToken returns an ExtractorSource that reads a Bearer token from the Authorization header. Uses case-insensitive prefix matching.

func FromCookie

func FromCookie(name string) ExtractorSource

FromCookie returns an ExtractorSource that reads from a plain cookie.

func FromCookieEncrypted

func FromCookieEncrypted(name string) ExtractorSource

FromCookieEncrypted returns an ExtractorSource that reads from an encrypted cookie.

func FromCookieSigned

func FromCookieSigned(name string) ExtractorSource

FromCookieSigned returns an ExtractorSource that reads from a signed cookie.

func FromForm

func FromForm(name string) ExtractorSource

FromForm returns an ExtractorSource that reads from a form field.

func FromHeader

func FromHeader(name string) ExtractorSource

FromHeader returns an ExtractorSource that reads from a request header.

func FromParam

func FromParam(name string) ExtractorSource

FromParam returns an ExtractorSource that reads from a URL parameter.

func FromQuery

func FromQuery(name string) ExtractorSource

FromQuery returns an ExtractorSource that reads from a query parameter.

func FromSession

func FromSession(key string) ExtractorSource

FromSession returns an ExtractorSource that reads from a session value. Tries string type assertion first, falls back to fmt.Sprint for non-string values.

type FingerprintMode

type FingerprintMode = internal.FingerprintMode

FingerprintMode determines which fingerprint generation algorithm to use.

type FingerprintStrictness

type FingerprintStrictness = internal.FingerprintStrictness

FingerprintStrictness determines behavior on fingerprint mismatch.

type HTTPError

type HTTPError = internal.HTTPError

HTTPError represents an HTTP error with all data needed for rendering.

func AsHTTPError

func AsHTTPError(err error) *HTTPError

AsHTTPError extracts the HTTPError from an error if present. Returns nil if the error is not an HTTPError.

func ErrBadRequest

func ErrBadRequest(message string, opts ...HTTPErrorOption) *HTTPError

ErrBadRequest creates a 400 Bad Request error.

func ErrConflict

func ErrConflict(message string, opts ...HTTPErrorOption) *HTTPError

ErrConflict creates a 409 Conflict error.

func ErrForbidden

func ErrForbidden(message string, opts ...HTTPErrorOption) *HTTPError

ErrForbidden creates a 403 Forbidden error.

func ErrInternal

func ErrInternal(message string, opts ...HTTPErrorOption) *HTTPError

ErrInternal creates a 500 Internal Server Error.

func ErrNotFound

func ErrNotFound(message string, opts ...HTTPErrorOption) *HTTPError

ErrNotFound creates a 404 Not Found error.

func ErrServiceUnavailable

func ErrServiceUnavailable(message string, opts ...HTTPErrorOption) *HTTPError

ErrServiceUnavailable creates a 503 Service Unavailable error.

func ErrTooManyRequests

func ErrTooManyRequests(message string, opts ...HTTPErrorOption) *HTTPError

ErrTooManyRequests creates a 429 Too Many Requests error.

func ErrUnauthorized

func ErrUnauthorized(message string, opts ...HTTPErrorOption) *HTTPError

ErrUnauthorized creates a 401 Unauthorized error.

func ErrUnprocessable

func ErrUnprocessable(message string, opts ...HTTPErrorOption) *HTTPError

ErrUnprocessable creates a 422 Unprocessable Entity error.

func NewHTTPError

func NewHTTPError(code int, message string) *HTTPError

NewHTTPError creates a new HTTPError with the given status code and message.

type HTTPErrorOption

type HTTPErrorOption = internal.HTTPErrorOption

HTTPErrorOption configures an HTTPError.

func WithDetail

func WithDetail(detail string) HTTPErrorOption

WithDetail sets the extended description.

func WithError

func WithError(err error) HTTPErrorOption

WithError sets the underlying error.

func WithErrorCode

func WithErrorCode(code string) HTTPErrorOption

WithErrorCode sets the application-specific error code.

func WithRequestID

func WithRequestID(id string) HTTPErrorOption

WithRequestID sets the request tracking ID.

func WithTitle

func WithTitle(title string) HTTPErrorOption

WithTitle sets the error title.

type Handler

type Handler = internal.Handler

Handler declares routes on a router.

type HandlerFunc

type HandlerFunc = internal.HandlerFunc

HandlerFunc is the signature for route handlers.

type HealthCheckOption

type HealthCheckOption = internal.HealthCheckOption

HealthCheckOption adds a readiness check to the health configuration.

func HealthCheck

func HealthCheck(name string, fn CheckFunc) HealthCheckOption

HealthCheck creates a named readiness check for use with WithHealthChecks.

type I18nOption

type I18nOption = middlewares.I18nOption

I18nOption configures the I18n middleware.

func WithI18nDefaultFormat

func WithI18nDefaultFormat(f *i18n.LocaleFormat) I18nOption

WithI18nDefaultFormat sets the fallback locale format.

func WithI18nExtractor

func WithI18nExtractor(ext Extractor) I18nOption

WithI18nExtractor sets a custom language extractor chain.

func WithI18nFormatMap

func WithI18nFormatMap(m map[string]*i18n.LocaleFormat) I18nOption

WithI18nFormatMap sets the language-to-format mapping.

type JWTClaimsKey

type JWTClaimsKey = internal.JWTClaimsKey

JWTClaimsKey is the context key used to store parsed JWT claims.

type JWTOption

type JWTOption = middlewares.JWTOption

JWTOption configures the JWT middleware.

func WithJWTExtractor

func WithJWTExtractor(ext Extractor) JWTOption

WithJWTExtractor sets a custom token extractor for the JWT middleware.

type LanguageKey

type LanguageKey = internal.LanguageKey

LanguageKey is the context key used to store the resolved language string.

type Middleware

type Middleware = internal.Middleware

Middleware wraps a HandlerFunc to add cross-cutting concerns.

type Option

type Option = internal.Option

Option configures the application.

func WithCookieConfig

func WithCookieConfig(cfg cookie.Config) Option

WithCookieConfig configures the cookie manager.

func WithCustomLogger

func WithCustomLogger(l *slog.Logger) Option

WithCustomLogger sets a fully custom logger. Use this when you need complete control over logging configuration.

func WithErrorHandler

func WithErrorHandler(h ErrorHandler) Option

WithErrorHandler sets a custom error handler for handler errors. Called when a handler returns a non-nil error.

func WithHandlers

func WithHandlers(h ...Handler) Option

WithHandlers registers handlers that declare routes. Each handler's Routes method is called during setup.

func WithHealthChecks

func WithHealthChecks(checks ...HealthCheckOption) Option

WithHealthChecks enables health check endpoints. Liveness: /_live — always returns OK if process is running. Readiness: /_ready — runs all configured checks.

func WithJobEnqueuer

func WithJobEnqueuer(pool *pgxpool.Pool, opts ...job.EnqueuerOption) Option

WithJobEnqueuer enables job enqueueing without worker processing. Use this for web servers that dispatch work to separate worker processes. Workers must be running elsewhere to process the enqueued jobs.

func WithJobWorker

func WithJobWorker(pool *pgxpool.Pool, cfg job.Config, opts ...job.Option) Option

WithJobWorker enables job processing without enqueueing capability. Use this for dedicated background worker processes that don't need to dispatch additional jobs. Workers are started automatically when the app runs and stopped gracefully during shutdown.

func WithJobs

func WithJobs(pool *pgxpool.Pool, cfg job.Config, opts ...job.Option) Option

WithJobs enables both job enqueueing and worker processing using River. A pgxpool.Pool is required for the job queue. Workers are started automatically when the app runs and stopped gracefully during shutdown.

func WithLogger

func WithLogger(component string, extractors ...logger.ContextExtractor) Option

WithLogger creates a logger with a component name and optional extractors. The component name is added to every log entry for easy filtering. Extractors pull values from context (e.g., request_id, user_id).

func WithMethodNotAllowedHandler

func WithMethodNotAllowedHandler(h HandlerFunc) Option

WithMethodNotAllowedHandler sets a custom 405 handler.

func WithMiddleware

func WithMiddleware(mw ...Middleware) Option

WithMiddleware adds global middleware to the application. Middleware is applied in the order provided.

func WithNotFoundHandler

func WithNotFoundHandler(h HandlerFunc) Option

WithNotFoundHandler sets a custom 404 handler.

func WithRoles

func WithRoles(permissions RolePermissions, extractor RoleExtractorFunc) Option

WithRoles configures role-based access control for the application. The permissions map defines which permissions each role grants. The extractor function determines the current user's role from the request context. Roles are extracted lazily (once per request) and cached.

func WithSSEKeepAlive

func WithSSEKeepAlive(d time.Duration) Option

WithSSEKeepAlive sets the interval for SSE keepalive comments. Defaults to 30 seconds if not set or if d <= 0.

func WithSession

func WithSession(store SessionStore, opts ...SessionOption) Option

WithSession enables server-side session management. A SessionStore implementation must be provided (e.g., PostgresStore). Sessions are loaded lazily and saved automatically before the response is written.

Example:

app := forge.New(
    forge.WithSession(postgresStore,
        forge.WithSessionTTL(7 * 24 * time.Hour),        // 7 days
        forge.WithMaxSessionsPerUser(3),                  // Max 3 devices
        forge.WithSessionFingerprint(
            forge.FingerprintCookie,                     // Mode
            forge.FingerprintWarn,                       // Strictness
        ),
    ),
)

Sessions auto-create on first access. No manual c.InitSession() required.

func WithStaticFiles

func WithStaticFiles(pattern string, fsys fs.FS, subDir string) Option

WithStaticFiles mounts a static file handler at the given pattern. Directory listings are disabled. Files are served with default cache headers.

func WithStorage

func WithStorage(s storage.Storage) Option

WithStorage configures file storage for the application. A storage.Storage implementation must be provided (e.g., S3Client). Enables c.Upload(), c.UploadFromURL(), c.Download(), c.DeleteFile(), and c.FileURL().

type PanicError

type PanicError = middlewares.PanicError

PanicError represents a recovered panic.

func AsPanicError

func AsPanicError(err error) (*PanicError, bool)

AsPanicError extracts the PanicError from an error if present.

type Permission

type Permission = internal.Permission

Permission represents a named permission string.

type RateLimitOption

type RateLimitOption = middlewares.RateLimitOption

RateLimitOption configures the RateLimit middleware.

type ResponseWriter

type ResponseWriter = internal.ResponseWriter

ResponseWriter wraps http.ResponseWriter with hooks and HTMX support.

type RoleExtractorFunc

type RoleExtractorFunc = internal.RoleExtractorFunc

RoleExtractorFunc extracts the current user's role from the request context.

type RolePermissions

type RolePermissions = internal.RolePermissions

RolePermissions maps role names to their granted permissions.

type Router

type Router = internal.Router

Router is the interface handlers use to declare routes.

type RunConfig

type RunConfig = internal.RunConfig

RunConfig holds externally configurable runtime settings.

type RunOption

type RunOption = internal.RunOption

RunOption configures the server runtime.

func WithContext

func WithContext(ctx context.Context) RunOption

WithContext sets a custom base context for signal handling. Useful for testing or when integrating with existing context hierarchies. Defaults to context.Background() if not set.

func WithDomain

func WithDomain(pattern string, app *App) RunOption

WithDomain maps a host pattern to an App. Patterns: "api.example.com" (exact) or "*.example.com" (wildcard)

func WithFallback

func WithFallback(app *App) RunOption

WithFallback sets the default App for requests that don't match any domain. If no domains are configured, the fallback becomes the main handler.

func WithRunLogger

func WithRunLogger(l *slog.Logger) RunOption

WithRunLogger sets the application logger for the runtime. If nil, logging is disabled.

func WithShutdownHook

func WithShutdownHook(fn func(context.Context) error) RunOption

WithShutdownHook registers a cleanup function to run during shutdown. Hooks are called in the order they were registered. Each hook receives a context with the shutdown timeout.

func WithStartupHook

func WithStartupHook(fn func(context.Context) error) RunOption

WithStartupHook registers a function to run during server startup. Hooks are called in the order they were registered, after the port is bound but before serving requests. If any hook fails, the server stops and returns the error.

type SSEEvent

type SSEEvent = internal.SSEEvent

SSEEvent represents a Server-Sent Event to be streamed to the client.

type Session

type Session = internal.Session

Session represents a user session with metadata and data.

type SessionOption

type SessionOption = internal.SessionOption

SessionOption configures the session manager.

type SessionStore

type SessionStore = internal.Store

SessionStore defines the interface for session persistence.

type TranslatorKey

type TranslatorKey = internal.TranslatorKey

TranslatorKey is the context key used to store the i18n Translator.

type ValidationErrors

type ValidationErrors = internal.ValidationErrors

ValidationErrors is a collection of validation errors.

Directories

Path Synopsis
Package forgetest provides a fluent testing API for forge HTTP handlers.
Package forgetest provides a fluent testing API for forge HTTP handlers.
Package internal provides the core types and implementation for the Forge framework.
Package internal provides the core types and implementation for the Forge framework.
Package middlewares provides HTTP middleware for Forge applications.
Package middlewares provides HTTP middleware for Forge applications.
pkg
binder
Package binder provides comprehensive HTTP request data binding utilities for Go web applications.
Package binder provides comprehensive HTTP request data binding utilities for Go web applications.
cache
Package cache provides a generic Cache interface with in-memory and Redis implementations.
Package cache provides a generic Cache interface with in-memory and Redis implementations.
clientip
Package clientip extracts real client IP addresses from HTTP requests.
Package clientip extracts real client IP addresses from HTTP requests.
cookie
Package cookie provides HTTP cookie management with optional signing and encryption.
Package cookie provides HTTP cookie management with optional signing and encryption.
db
Package db provides PostgreSQL database utilities optimized for SaaS applications.
Package db provides PostgreSQL database utilities optimized for SaaS applications.
dnsverify
Package dnsverify provides DNS-based domain ownership verification.
Package dnsverify provides DNS-based domain ownership verification.
fingerprint
Package fingerprint provides device fingerprinting from HTTP requests for session validation and security.
Package fingerprint provides device fingerprinting from HTTP requests for session validation and security.
geolocation
Package geolocation provides IP geolocation lookups via MaxMind GeoIP2/GeoLite2 databases.
Package geolocation provides IP geolocation lookups via MaxMind GeoIP2/GeoLite2 databases.
hostrouter
Package hostrouter provides host-based HTTP routing.
Package hostrouter provides host-based HTTP routing.
htmx
Package htmx provides utilities for working with HTMX requests and responses.
Package htmx provides utilities for working with HTMX requests and responses.
i18n
Package i18n provides internationalization support with immutable, thread-safe design and comprehensive locale handling for Go applications.
Package i18n provides internationalization support with immutable, thread-safe design and comprehensive locale handling for Go applications.
id
Package id provides sortable ID generation utilities for use throughout the framework.
Package id provides sortable ID generation utilities for use throughout the framework.
job
Package job provides background job processing using River (Postgres-native queue).
Package job provides background job processing using River (Postgres-native queue).
jwt
Package jwt provides RFC 7519 compliant JSON Web Token implementation using HMAC-SHA256.
Package jwt provides RFC 7519 compliant JSON Web Token implementation using HMAC-SHA256.
logger
Package logger provides structured logging with context extraction and Sentry integration.
Package logger provides structured logging with context extraction and Sentry integration.
mailer
Package mailer provides a universal email sending interface with template rendering.
Package mailer provides a universal email sending interface with template rendering.
mailer/smtp
Package smtp provides an SMTP adapter that implements mailer.Sender using only the Go standard library.
Package smtp provides an SMTP adapter that implements mailer.Sender using only the Go standard library.
oauth
Package oauth provides OAuth2 authorization code flow implementations for common providers.
Package oauth provides OAuth2 authorization code flow implementations for common providers.
qrcode
Package qrcode generates QR code images from string content.
Package qrcode generates QR code images from string content.
randomname
Package randomname generates human-readable random names using cryptographically secure randomness.
Package randomname generates human-readable random names using cryptographically secure randomness.
ratelimit
Package ratelimit provides a sliding window rate limiter with pluggable storage backends.
Package ratelimit provides a sliding window rate limiter with pluggable storage backends.
redis
Package redis provides Redis client utilities optimized for SaaS applications.
Package redis provides Redis client utilities optimized for SaaS applications.
sanitizer
Package sanitizer provides comprehensive input sanitization and data cleaning utilities for web applications.
Package sanitizer provides comprehensive input sanitization and data cleaning utilities for web applications.
secrets
Package secrets provides AES-256-GCM encryption with compound key derivation for tenant-isolated data encryption in multi-tenant SaaS applications.
Package secrets provides AES-256-GCM encryption with compound key derivation for tenant-isolated data encryption in multi-tenant SaaS applications.
slug
Package slug generates URL-safe slugs from arbitrary strings with Unicode normalization.
Package slug generates URL-safe slugs from arbitrary strings with Unicode normalization.
storage
Package storage provides S3-compatible file storage operations.
Package storage provides S3-compatible file storage operations.
token
Package token provides compact URL-safe signed tokens with truncated HMAC-SHA256.
Package token provides compact URL-safe signed tokens with truncated HMAC-SHA256.
totp
Package totp provides RFC 6238 compliant Time-based One-Time Password (TOTP) authentication with AES-256-GCM secret encryption and backup recovery codes.
Package totp provides RFC 6238 compliant Time-based One-Time Password (TOTP) authentication with AES-256-GCM secret encryption and backup recovery codes.
totp/cmd command
useragent
Package useragent provides User-Agent string parsing to extract browser, operating system, and device information for web analytics, content optimization, and request handling.
Package useragent provides User-Agent string parsing to extract browser, operating system, and device information for web analytics, content optimization, and request handling.
validator
Package validator provides a rule-based data validation system with both programmatic and struct tag-based validation capabilities.
Package validator provides a rule-based data validation system with both programmatic and struct tag-based validation capabilities.
webhook
Package webhook provides reliable HTTP webhook delivery with automatic retries and circuit breaking.
Package webhook provides reliable HTTP webhook delivery with automatic retries and circuit breaking.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL