# flux
flux is a modern, full-stack web framework for Go — designed to combine developer happiness, performance, and structure.
flux make:controller, make:model, make:microservice, etc.flux is built on top of the Fiber web framework for several reasons:
While we could have built directly on Go's standard library, we chose Fiber to provide better performance and developer experience. The flux framework abstracts away most Fiber-specific details, allowing you to work with a clean, consistent API.
While flux is built on top of Fiber for its performance benefits, it offers several significant advantages:
Standardized project layout for sustainable development
Powerful Middleware System
Built-in middleware for common tasks (logging, auth, rate limiting)
Full-Stack Development Framework
Extensible plugin architecture
Dual Architecture Support
Shared tools and patterns across both architectures
Developer-Friendly Tooling
go install github.com/Fluxgo/flux/cmd/flux@latest
Create a new flux project:
flux new myapp
cd myapp
Generate a controller:
flux make:controller User
Generate a model:
flux make:model Post --migration
Start the development server:
flux serve
Create a new microservice:
flux make:microservice user-service
cd user-service
Optional flags for microservice creation:
- --with-db: Include database integration
- --with-auth: Include authentication support
- --with-cache: Include Redis cache integration
- --with-queue: Include task queue support
Sample with options:
flux make:microservice payment-service --with-db --with-auth
flux supports two primary architectural patterns:
Best for: - Smaller teams and projects - Rapid prototyping - Applications with simpler domains
Structure:
myapp/
├── app/
│ ├── controllers/ # Route handlers
│ ├── services/ # Business logic
│ ├── models/ # DB schemas
├── config/ # App/env config
├── database/ # Migrations/seeders
├── routes/ # Route groups
├── templates/ # Optional views
├── fluxflux.yaml # Project config
└── main.go
Best for: - Larger teams and projects - Complex domain boundaries - Scalable, distributed systems
Structure:
service-name/
├── api/ # API layer
│ ├── handlers/ # HTTP request handlers
│ └── middleware/ # HTTP middleware
├── cmd/ # Application entry points
│ └── service-name/ # Main service executable
├── config/ # Configuration files
├── internal/ # Private application code
│ ├── models/ # Data models
│ ├── services/ # Business logic
│ └── repositories/ # Data access layer
└── pkg/ # Public libraries
└── logger/ # Logging utilities
package controllers
import (
"github.com/Fluxgo/flux/pkg/flux"
)
// UserController handles user-related requests
type UserController struct {
flux.Controller
}
// LoginRequest represents the login request body
type LoginRequest struct {
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required,min=8"`
}
// HandlePostLogin handles user login
// @route POST /login
// @desc Authenticate a user
// @body LoginRequest
// @response 200 { message: string }
func (c *UserController) HandlePostLogin(ctx *flux.Context) error {
var req LoginRequest
if err := ctx.Bind(&req); err != nil {
return ctx.Status(400).JSON(flux.H{
"error": "Invalid request body",
})
}
// Implement actual login logic
return ctx.JSON(flux.H{
"message": "Welcome",
})
}
flux uses a convention-based approach to routing inspired by Ruby on Rails and Laravel. Controllers and their methods automatically map to HTTP routes.
Controllers should be named with the Controller suffix:
// UserController -> maps to "/user" route prefix
type UserController struct {
flux.Controller
}
// AuthController -> maps to "/auth" route prefix
type AuthController struct {
flux.Controller
}
Controller methods should follow this pattern:
Handle[HTTP Method][Action]
For example:
// HandleGetUsers maps to GET /user
func (c *UserController) HandleGetUsers(ctx *flux.Context) error {
// ...continue with implementation inside this wrapper
}
// HandlePostUser maps to POST /user
func (c *UserController) HandlePostUser(ctx *flux.Context) error {
// ...continue with implementation inside this wrapper
}
// HandlePutUserById maps to PUT /user/:id
func (c *UserController) HandlePutUserById(ctx *flux.Context) error {
id := ctx.Param("id")
// ...continue with implementation inside this wrapper
}
// HandleDeleteUser maps to DELETE /user
func (c *UserController) HandleDeleteUser(ctx *flux.Context) error {
// ...continue with implementation inside this wrapper
}
ById in the method name automatically maps to the path pattern with :id parameterHandleGetUserPosts maps to GET /user/postsTo register a controller with your flux application:
app.RegisterController(&UserController{})
app.RegisterController(&AuthController{})
Here's an example of a complete authentication controller:
package controllers
import (
"github.com/Fluxgo/flux/pkg/flux"
)
// AuthController handles authentication-related requests
type AuthController struct {
flux.Controller
}
// RegisterRequest represents the registration request body
type RegisterRequest struct {
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required,min=8"`
Name string `json:"name" validate:"required"`
}
// LoginRequest represents the login request body
type LoginRequest struct {
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required"`
}
// HandlePostRegister handles user registration
// Maps to: POST /auth/register
func (c *AuthController) HandlePostRegister(ctx *flux.Context) error {
var req RegisterRequest
if err := ctx.Bind(&req); err != nil {
return ctx.Status(400).JSON(flux.H{
"error": "Invalid request body",
})
}
if err := ctx.Validate(&req); err != nil {
return ctx.Status(400).JSON(flux.H{
"error": "Validation failed",
"details": err.Error(),
})
}
// Add user registration logic here...
return ctx.Status(201).JSON(flux.H{
"message": "User registered successfully",
})
}
// HandlePostLogin handles user login
// Maps to: POST /auth/login
func (c *AuthController) HandlePostLogin(ctx *flux.Context) error {
var req LoginRequest
if err := ctx.Bind(&req); err != nil {
return ctx.Status(400).JSON(flux.H{
"error": "Invalid request body",
})
}
if err := ctx.Validate(&req); err != nil {
return ctx.Status(400).JSON(flux.H{
"error": "Validation failed",
"details": err.Error(),
})
}
// user authentication logic here...
token := "sample-jwt-token"
return ctx.JSON(flux.H{
"token": token,
"message": "Login successful",
})
}
You can impmentment start flux application server using any of these methods:
// Option 1: Using Start (recommended)
if err := app.Start(); err != nil {
log.Fatalf("Failed to start server: %v", err)
}
// Option 2: Using Listen (Fiber-style)
if err := app.Listen(":3000"); err != nil {
log.Fatalf("Failed to start server: %v", err)
}
// Option 3: Using Serve (net/http-style)
if err := app.Serve(); err != nil {
log.Fatalf("Failed to start server: %v", err)
}
flux provides a powerful middleware system inspired by Express.js. Middleware functions have access to the request/response cycle and can:
// Simple middleware function
func LoggingMiddleware(next flux.HandlerFunc) flux.HandlerFunc {
return func(ctx *flux.Context) error {
start := time.Now()
// Call the next handler in the chain
err := next(ctx)
// Log after the request is processed
duration := time.Since(start)
ctx.App().Logger().Info("Request processed in %s", duration)
return err
}
}
Middleware can be applied at multiple levels:
// Apply middleware to a controller
userController := &UserController{}
userController.Use(middleware.RequestLogger(), middleware.RequireAuth())
// Register the controller
app.RegisterController(userController)
// Create a group with shared middleware
api := (&flux.Controller{}).Group("/api")
api.Use(middleware.Recover(), middleware.RequestLogger())
// Add controllers to the group
api.Add(&UserController{})
api.Add(&ProductController{})
// Register all controllers in the group
api.Register(app)
// Apply middleware to all routes
app.Use(middleware.Recover(), middleware.RequestLogger())
flux comes with several built-in middleware functions:
middleware.RequestLogger() - Logs request information and timingmiddleware.Recover() - Catches panics and converts them to errorsmiddleware.RequireAuth() - Handles authentication checksmiddleware.CORS(options) - Configures CORS headersmiddleware.RateLimit(limit) - Limits request ratesmiddleware.Timeout(duration) - Sets a timeout for request handlingflux includes built-in CORS support. Configure it in your application:
app, err := flux.New(&flux.Config{
CORS: flux.CORSConfig{
AllowOrigins: "http://localhost:3000,https://ffg.com",
AllowMethods: "GET,POST,PUT,DELETE",
AllowHeaders: "Origin, Content-Type, Accept, Authorization",
AllowCredentials: true,
MaxAge: 86400,
},
})
If not specified, flux uses a permissive default CORS configuration that allows all origins.
flux uses GORM for database operations. Here's an example model:
package models
// User represents a user entity
type User struct {
ID uint `json:"id" gorm:"primaryKey"`
Email string `json:"email" gorm:"uniqueIndex"`
Name string `json:"name"`
CreatedAt string `json:"created_at" gorm:"autoCreateTime"`
UpdatedAt string `json:"updated_at" gorm:"autoUpdateTime"`
}
// TableName returns the table name for the model
func (User) TableName() string {
return "users"
}
Configure your application in flux.yaml:
app:
name: "myapp"
version: "0.1.0"
description: "A flux application"
server:
port: 3000
host: localhost
base_path: /
database:
driver: sqlite
name: flux.db
flux new [name]: Create a new monolithic flux projectflux make:controller [name]: Generate a new controllerflux make:model [name]: Generate a new modelflux make:microservice [name]: Generate a new microservice projectflux serve: Start the development server with hot reloadflux db:migrate: Run database migrationsflux doc:generate: Generate OpenAPI documentationflux provides first-class support for building microservices with a modern, production-ready structure: