What is Lokstra?
A versatile Go web framework that works in two ways: as a Router or as a complete Business Application Framework
π― Two Ways to Use Lokstra
Lokstra is designed to meet you where you are:
π― Track 1: As a Router (Like Echo, Gin, Chi)
Quick, simple HTTP routing without framework complexity
Use Lokstra as a pure HTTP router for:
- Quick prototypes and MVPs
- Simple REST APIs
- Learning HTTP routing fundamentals
- Projects without DI needs
r := lokstra.NewRouter("api")
r.GET("/users", getUsersHandler)
r.Use(cors.Middleware("*"))
app := lokstra.NewApp("api", ":8080", r)
app.Run(30 * time.Second)
Compare with: Echo, Gin, Chi, Fiber
Learn more: Router Guide
οΏ½οΈ Track 2: As a Business Application Framework (Like NestJS, Spring Boot)
Enterprise features with DI, auto-router, and configuration-driven deployment
Use Lokstra as a complete framework for:
- Enterprise applications
- Microservices architectures
- Dependency injection and service layer
- Configuration-driven deployment
- Annotation-driven development (like NestJS decorators)
With Lokstra Annotations (Recommended) - Zero boilerplate!
// @RouterService name="user-service", prefix="/api"
type UserServiceImpl struct {
// @Inject "user-repository"
UserRepo domain.UserRepository
}
// @Route "GET /users/{id}"
func (s *UserServiceImpl) GetByID(p *GetUserRequest) (*User, error) {
return s.UserRepo.GetByID(p.ID)
}
// Auto-generates: factory, remote proxy, routes, DI wiring!
Or traditional approach (YAML/Code):
# Define services in YAML
service-definitions:
user-service:
type: user-service-factory
depends-on: [database]
// Type-safe lazy loading
var userService = service.LazyLoad[*UserService]("user-service")
func handler() {
users := userService.MustGet().GetAll()
}
// Auto-router generates REST endpoints from service methods!
Compare with: NestJS, Spring Boot, Uber Fx, Buffalo
Learn more: Framework Guide
π The Big Idea
Start simple, scale when needed:
- Start with routing (Track 1) for quick results
- Add services and DI when complexity grows (Track 2)
- Enable auto-router to reduce boilerplate
- Switch deployment topology without code changes
Lokstra grows with your needs!
π Core Concepts (5-Minute Overview)
Lokstra has 6 core components that work together:
1. Router - HTTP Routing
r := lokstra.NewRouter("api")
r.GET("/users", func() ([]User, error) {
return db.GetAllUsers()
})
Key Feature: Flexible handler signatures - many forms supported!
2. Service - Business Logic
type UserService struct {}
func (s *UserService) GetAll() ([]User, error) {
return db.Query("SELECT * FROM users")
}
// Register service type (factory creates instances)
lokstra_registry.RegisterServiceType("user-service", func() any {
return &UserService{}
}, nil)
Key Feature: Service methods can become HTTP endpoints automatically!
3. Middleware - Request Processing
r.Use(recovery.Middleware(nil), cors.Middleware("*"))
Key Feature: Apply middleware globally or per-route
4. Configuration - YAML or Code
deployments:
production:
servers:
web-server:
base-url: http://localhost
addr: ":8080"
published-services: [user-service]
Key Feature: One config file for multiple deployments
5. App - Application Container
app := lokstra.NewApp("my-app", ":8080", router)
Key Feature: Combine multiple routers into one app
6. Server - Server Manager
server := lokstra.NewServer("main", app)
server.Run(30 * time.Second) // Graceful shutdown
Key Feature: Manage multiple apps, automatic graceful shutdown
π Your First Lokstra App
Complete working example in 20 lines:
package main
import (
"github.com/primadi/lokstra"
"time"
)
func main() {
// 1. Create router
r := lokstra.NewRouter("api")
// 2. Register routes
r.GET("/ping", func() string {
return "pong"
})
r.GET("/users", func() []string {
return []string{"Alice", "Bob", "Charlie"}
})
// 3. Create app & run
app := lokstra.NewApp("demo", ":8080", r)
app.PrintStartInfo()
if err := app.Run(30 * time.Second); err != nil {
log.Fatal(err)
}
}
Test it:
curl http://localhost:8080/ping # β "pong"
curl http://localhost:8080/users # β ["Alice","Bob","Charlie"]
π Note: This is a simplified introduction example. For complete runnable examples with proper project structure, see:
- Quick Start - Your first working API in 5 minutes
- Examples - 4 progressive examples from basics to production
π‘ What Makes Lokstra Different?
1. Flexible Handler Signatures
Youβre not locked into one pattern. Write handlers that make sense:
// Simple
r.GET("/ping", func() string { return "pong" })
// With error
r.GET("/users", func() ([]User, error) {
return db.GetUsers()
})
// With context
r.POST("/users", func(ctx *request.Context, user *User) error {
result, err := db.Save(user)
if err != nil {
return ctx.Api.InternalError(err.Error())
}
return ctx.Api.Ok(result)
})
// With response.ApiHelper
r.GET("/complex", func(user *User) (*response.ApiHelper, error) {
result, err := db.Save(user)
if err != nil {
return nil, err
}
return response.NewApiOk(result), nil
})
29+ different handler forms supported!
2. Service as Router (Game Changer!)
Your service methods automatically become HTTP endpoints:
// Step 1: Define service with methods
type UserService struct {}
type GetAllParams struct {}
type GetByIDParams struct {
ID string `path:"id"`
}
type CreateUserParams struct {
User *User `json:"user"`
}
func (s *UserService) GetAll(p *GetAllParams) ([]User, error) { ... }
func (s *UserService) GetByID(p *GetByIDParams) (*User, error) { ... }
func (s *UserService) Create(p *CreateUserParams) error { ... }
func NewUserService() *UserService {
return &UserService{}
}
// Step 2: Register service factory with metadata
lokstra_registry.RegisterServiceType(
"user-service-factory",
NewUserService,
nil,
deploy.WithResource("user", "users"),
deploy.WithConvention("rest"),
)
// Step 3: Auto-generate router from service!
userRouter := lokstra_registry.NewRouterFromServiceType("user-service-factory")
// Automatically creates:
// GET /users β GetAll() method
// GET /users/{id} β GetByID() method
// POST /users β Create() method
Zero boilerplate routing code!
3. One Binary, Multiple Deployments
Configure once, deploy anywhere:
deployments:
monolith:
servers:
web-server:
addr: ":8080"
published-services: [users, orders, payments]
multi-server:
servers:
user-service:
base-url: http://user-service
addr: ":8001"
published-services: [users]
order-payment-service:
base-url: http://order-payment-service
addr: ":8002"
published-services: [orders, payments]
Same code, different architectures - just change config!
# Run as monolith
./app --server=monolith
# Run as microservice
./app --server=user-service
4. Built-in Dependency Injection
No external DI framework needed:
import "github.com/primadi/lokstra/core/service"
type UserService struct {
DB *Database
}
// Register factories
lokstra_registry.RegisterServiceType("db-factory", createDBFactory, nil)
lokstra_registry.RegisterServiceType("users-factory",
func(deps map[string]any, config map[string]any) any {
return &UserService{
DB: deps["db"].(*Database),
}
}, nil)
// Service-level lazy loading - service created on first access
users := lokstra_registry.GetService[*UserService]("users")
// Inside service method - dependencies already injected
func (u *UserService) GetUsers() ([]User, error) {
return u.DB.Query("SELECT * FROM users")
}
Key Feature: Service-level lazy loading - services created only when needed, dependencies eagerly resolved!
ποΈ Architecture at a Glance
βββββββββββββββββββββββββββββββββββββββββββ
β HTTP Request β
βββββββββββββββ¬ββββββββββββββββββββββββββββ
β
βββββββββββββββΌββββββββββββββββββββββββββββ
β APP (with Listener) β
β (ServeMux / FastHTTP / HTTP2 / etc) β
β ββββββββββββββββββββββββββββββββββββββ β
β β ROUTER (http.Handler) β β
β β ββββββββββββββββββββββββββββββββ β β
β β β ROUTE β β β
β β β βββββββββββββββββββββββββ β β β
β β β β MidWare 1 (before) ββββΌββββΌβββΌββΌβββ
β β β ββββββββββ¬βββββββββββββββ β β β β
β β β ββββββββββΌβββββββββββββββ β β β β
β β β β MidWare 2 (before) ββββΌββββΌβββΌββΌβββ€
β β β ββββββββββ¬βββββββββββββββ β β β β
β β β ββββββββββΌβββββββββββββββ β β β β
β β β β HANDLER βββββΌββββΌβββΌββΌβββ€
β β β ββββββββββ¬βββββββββββββββ β β β β
β β β βββββββββββββββββββββββββ β β β β
β β β β MidWare 2 (after) ββββΌββββΌβββΌββΌβββ€
β β β ββββββββββ¬βββββββββββββββ β β β β
β β β ββββββββββΌβββββββββββββββ β β β β
β β β β MidWare 1 (after) ββββΌββββΌβββΌββΌβββ€
β β β ββββββββββ¬βββββββββββββββ β β β β
β β βββββββββββββΌβββββββββββββββββββ β β β
β ββββββββββββββββΌββββββββββββββββββββββ β β
βββββββββββββββββββΌββββββββββββββββββββββββ β
β βββββββββββββ
β ββββββββββΌββββββββββββ
β β SERVICES ββββββ
β β (business logic) β β
β β β β
β β Service can call: | β
β β - Other Services ββΌβββββ
β β - Database |
β β - External APIs |
β ββββββββββββββββββββββ
β
ββββββββββΌββββββββββ
β RESPONSE OBJECT β
β (formatting) β
ββββββββββββββββββββ
Request Flow:
- HTTP request arrives at Appβs listener
- Listener routes to Router (http.Handler)
- Router finds matching Route
- Route executes Middleware chain (via ctx.Next())
- Middleware can call Services (e.g., auth checks)
- Handler executes
- Handler can call Services
- Services contain business logic
- Services can call other Services
- Services can call databases, external APIs, etc.
- Response Object formats the response
- Response flows back to client
Key Points:
- Services are accessible everywhere: Middleware, Handlers, and other Services can all call Services
- Server is just a container for Apps, Services, and configuration - not part of request flow
- Middleware can use Services for auth, logging, etc.
- Services can depend on other Services (via Dependency Injection)
π What Youβll Learn
Choose your learning path:
Track 1: Router Only (2-3 hours)
β
Create routers and register routes
β
Write handlers in 29+ different styles
β
Apply middleware (global, per-route, groups)
β
Manage app and server lifecycle
β
Build REST APIs without DI
Track 2: Full Framework (6-8 hours)
β
Everything in Track 1, plus:
β
Service layer and dependency injection
β
Auto-generate routes from services
β
Configuration-driven deployment (YAML or Code)
β
Monolith β Microservices migration
β
External service integration
π¦ Where to Go Next?
New to Lokstra? Start Here:
Option 1: Quick Start (Fastest)
Just want to see it work?
- π Quick Start - Build your first API in 5 minutes
- π Examples - Router Track - 3 quick examples (2-3 hours)
Option 2: Understand First (Recommended)
Want to understand before coding?
- π Why Lokstra? - Compare with other frameworks
- π Architecture - Deep dive into design
- π Key Features - What makes Lokstra different
Ready to Learn? Choose Your Track:
Track 1: Router Only
For: Quick APIs, prototypes, simple projects
- Examples - Router Track - Hands-on learning (2-3 hours)
- Router Guide - Deep dive into routing
- API Reference - Router - Complete API
Track 2: Full Framework
For: Enterprise apps, microservices, DI architecture
- Examples - Framework Track - Hands-on learning (8-12 hours)
- Framework Guide - Services, DI, auto-router
- Configuration Reference - YAML schema
Not Sure Which Track?
Start with Track 1 (Router) if:
- New to Lokstra
- Building MVP or prototype
- Want quick results
- Donβt need DI yet
Start with Track 2 (Framework) if:
- Need dependency injection
- Building microservices
- Want auto-generated routers
- Familiar with NestJS/Spring Boot
Remember: You can always upgrade from Track 1 to Track 2 later!
π― Key Takeaways
Before moving on, remember:
- Lokstra is flexible - Use as router-only OR full framework
- Start simple, scale up - Begin with Track 1, upgrade to Track 2 when needed
- Convention over configuration - Smart defaults, configure when needed
- Service-oriented - Services are first-class citizens (Track 2)
- Deployment-agnostic - Same code, monolith or microservices (Track 2)
- Production-ready - Built for real applications
π Learning with Examples
We provide two example tracks based on how you want to use Lokstra:
Track 1: Router-Only Examples
β±οΈ 2-3 hours total β’ Perfect for quick APIs
- 01: Hello World - Basic routing (15 min)
- 02: Handler Forms - 29+ handler signatures (30 min)
- 03: Middleware - Global, per-route, groups (45 min)
What youβll build: REST APIs with routing and middleware (no DI)
Track 2: Full Framework Examples
β±οΈ 8-12 hours total β’ For enterprise apps
- 01: CRUD with Services - Service layer, DI (1 hour)
- 02: Multi-Deployment YAML - Auto-router, microservices (2-3 hours)
- 03: Multi-Deployment Code - Type-safe config (30 min)
- 04: External Services - proxy.Service patterns (1-2 hours)
- 05: Remote Router - Quick HTTP integration (30 min)
What youβll build: Enterprise apps with DI, auto-router, and microservices
π€ Which Track to Choose?
| Β | Router Track | Framework Track |
|---|---|---|
| Time | 2-3 hours | 8-12 hours |
| Use Case | Quick APIs, prototypes | Enterprise, microservices |
| Features | Routing, middleware | + DI, auto-router, config |
| Compare With | Echo, Gin, Chi | NestJS, Spring Boot |
Not sure? Start with Router Track (itβs compatible with Framework features!)
οΏ½π Roadmap
Next Release
Weβre actively working on:
- π¨ HTMX Support - Build modern web apps easier
- Template rendering integration
- Partial page updates
- Form handling patterns
- Example applications
- π οΈ CLI Tools - Developer productivity
- Project scaffolding (
lokstra new) - Code generation (
lokstra generate) - Migration helpers
- Development server
- Project scaffolding (
- π¦ Complete Standard Library - Production essentials
- Middleware: Metrics, Auth (JWT, OAuth), Rate limiting
- Services: Monitoring, Tracing, Health checks
- Utilities: Common patterns and helpers
Want to contribute or suggest features? Visit our GitHub repository
Ready? β Continue to Why Lokstra? or jump straight to Quick Start