Production-ready Go web framework built on Fiber, designed for enterprise applications with modular architecture, dependency injection, and batteries included.
The project is organized as follows:
.
├── cmd
│ └── server # Contains the main function to start the server
├── docs # Generated API documentation
├── internal
│ ├── common # Shared components (models, types, validators)
│ ├── configs # Configuration management module (using Viper)
│ ├── database # Database connection management module (using GORM)
│ ├── modules # Contains business logic modules (e.g., users, health_check)
│ │ ├── combine_module.go # Aggregates all modules
│ │ └── {module}/ # Individual modules
│ └── server # Fiber server configuration and initialization
├── pkg
│ └── http_error # Helper for handling HTTP errors
├── .air.toml # Configuration for live-reloading with Air
├── .env # File for environment variables (should be created from example.env)
├── example.env # Example file for environment variables
├── go.mod # Declares the Go module and its dependencies
├── taskfile.yml # Contains commands to build, run, and manage the project
└── ...
- Go (version 1.25.0 or newer)
- PostgreSQL
- Air (optional, for live-reloading)
- Task (required for running commands)
- Swag (required for generating docs)
-
Clone the repository:
git clone https://github.com/l1ttps/fiberest cd fiberest -
Install dependencies:
go mod tidy
-
Configure environment variables:
Create a
.envfile from theexample.envfile and update the values to match your environment.cp example.env .env
The
.envfile will look like this:PORT=3278 # PostgreSQL Configuration DB_HOST=localhost DB_PORT=5432 DB_USER=postgres DB_PASSWORD=your_password DB_NAME=fiberest DB_SSLMODE=disable
-
Run the project:
Use
taskto run the project.-
Development mode (with hot reload):
task dev
Note:
task devrunstask docsbefore building (via.air.tomlpre_cmd). -
Normal execution:
task run
Note:
task rundepends ondocsand runs it first.
-
This project follows a modular architecture. Each business feature should be organized as a separate module in internal/modules/.
To create a new module:
-
Create directory structure:
mkdir -p internal/modules/{module_name}/{dto,models} -
Create core files:
touch internal/modules/{module_name}/{module_name}.module.go touch internal/modules/{module_name}/{module_name}.controller.go touch internal/modules/{module_name}/{module_name}.service.go -
Module definition (
{module}.module.go):package {module_name} import "go.uber.org/fx" var Module = fx.Options( fx.Provide(NewService), // Provide business logic service fx.Provide(NewController), // Provide HTTP controller fx.Invoke(RegisterRoutes), // Register HTTP routes )
Note: Route registration function name varies (e.g.,
UserRoutesin users module). -
Register module: Add your module to
internal/modules/combine_module.go:import "fiberest/internal/modules/{module_name}" var Module = fx.Options( // ... existing modules {module_name}.Module, )
Critical: Both steps (module file + combine_module.go) are required.
Routes are registered in the controller's route registration function:
func RegisterRoutes(app *fiber.App, controller *Controller) {
group := app.Group("/api/v1/{endpoint}")
group.Post("", controller.Create) // POST /api/v1/{endpoint}
group.Get("", controller.List) // GET /api/v1/{endpoint}
group.Get("/:id", controller.Get) // GET /api/v1/{endpoint}/:id
group.Put("/:id", controller.Update) // PUT /api/v1/{endpoint}/:id
group.Delete("/:id", controller.Delete) // DELETE /api/v1/{endpoint}/:id
}The project uses Uber FX for dependency injection. All dependencies are automatically resolved:
// Service depends on DatabaseService
func NewService(dbService *database.DatabaseService) *Service {
return &Service{dbService: dbService}
}
// Controller depends on Service
func NewController(service *Service) *Controller {
return &Controller{service: service}
}FX automatically handles the lifecycle and injection of all provided components.
Critical DI Chain: server.Module depends on auth.AuthService. The auth module's AutoMigrate runs automatically on startup.
Use the injected DatabaseService to access GORM:
// Get database instance
db := s.dbService.DB
// Create record
err := db.Create(&user).Error
// Find record
err := db.First(&user, id).Error
// Update record
err := db.Model(&user).Updates(User{Name: "New Name"}).Error
// Delete record
err := db.Delete(&user, id).Error
// Transactions
err := db.Transaction(func(tx *gorm.DB) error {
// Multiple operations that must succeed together
if err := tx.Create(&user).Error; err != nil {
return err
}
return tx.Create(&profile).Error
})Use the built-in validator to validate incoming requests:
import "fiberest/internal/common/validators"
func (c *Controller) Create(ctx fiber.Ctx) error {
var req dto.CreateUserRequest
if err := validators.ParseAndValidate(ctx, &req); err != nil {
return validators.ResponseError(ctx, err)
}
// Process valid request
}Fiberest provides pre-built middlewares for common security and rate limiting needs.
JWT-based authentication middleware that protects routes. Automatically checks for tokens in cookies (access_token) or Authorization: Bearer header.
import "fiberest/internal/middlewares"
// Apply globally (recommended) - protects all routes except public ones
app.Use(middlewares.AuthGuard(config))
// Apply to specific route groups
group := app.Group("/api/v1/protected", middlewares.AuthGuard(config))Public routes (bypass authentication) are defined in internal/middlewares/auth_guard.go. Supports exact matches, prefix wildcards (/public/*), and suffix wildcards (*.html).
Rate limiting middleware to prevent abuse and protect API endpoints.
import "fiberest/internal/middlewares"
// Allow 100 requests per minute
app.Use(middlewares.Limiter(100, 60))
// Apply stricter limits to sensitive endpoints
group.Post("/login", middlewares.Limiter(5, 60), controller.Login)Add Swagger annotations to your controller handlers:
// @Summary Create a new user
// @Description Creates a new user in the system
// @Tags users
// @Accept json
// @Produce json
// @Param request body dto.CreateUserRequest true "User data"
// @Success 201 {object} dto.UserResponse
// @Failure 400 {object} http_error.ErrorResponse
// @Failure 409 {object} http_error.ErrorResponse
// @Router /api/v1/users [post]
func (c *Controller) Create(ctx fiber.Ctx) error {
// implementation
}Generate updated documentation:
task docsNote: Swagger docs are auto-generated before every build in dev mode (.air.toml pre_cmd).
task dev: Hot reload development mode (runstask docs→ build)task run: Build docs → run binarytask build: Build docs → compile binary (./bin/server)task docs: Generate Swagger docs (swag init -g cmd/server/main.go -o docs)
The project uses Scalar (not Swagger UI) for API documentation. After starting the server, access docs at:
http://localhost:3278/docs
Port is configurable via .env (default: 3278).