Installation
Homebrew (macOS/Linux)
Go Install
brew install abdul-hamid-achik/tap/fuego-cli
Create a Project
This creates:
The route.go in app/api/health/ automatically maps to GET /api/health.
Run Development Server
Visit http://localhost:3000
You’ll see:
Hot reload enabled
Request logging in your terminal
Tailwind CSS watching (if enabled)
Add an API Route
Create app/api/users/route.go:
package users
import " github.com/abdul-hamid-achik/fuego/pkg/fuego "
// GET /api/users
func Get ( c * fuego . Context ) error {
users := [] map [ string ] any {
{ "id" : 1 , "name" : "Alice" },
{ "id" : 2 , "name" : "Bob" },
}
return c . JSON ( 200 , users )
}
// POST /api/users
func Post ( c * fuego . Context ) error {
var user struct {
Name string `json:"name"`
}
if err := c . Bind ( & user ); err != nil {
return fuego . BadRequest ( "invalid request body" )
}
return c . JSON ( 201 , map [ string ] any {
"id" : 3 ,
"name" : user . Name ,
})
}
Now you have:
GET /api/users - List users
POST /api/users - Create user
Handler functions are named after HTTP methods: Get, Post, Put, Patch, Delete, Head, Options.
Test Your Endpoints
# List users
curl http://localhost:3000/api/users
# Create a user
curl -X POST http://localhost:3000/api/users \
-H "Content-Type: application/json" \
-d '{"name":"Charlie"}'
Add Middleware
Create app/api/middleware.go:
package api
import " github.com/abdul-hamid-achik/fuego/pkg/fuego "
// Middleware applies to all routes under /api/*
func Middleware () fuego . MiddlewareFunc {
return func ( next fuego . HandlerFunc ) fuego . HandlerFunc {
return func ( c * fuego . Context ) error {
c . SetHeader ( "X-API-Version" , "1.0" )
return next ( c )
}
}
}
This middleware automatically applies to all routes under /api/.
Add Dynamic Routes
Create app/api/users/[id]/route.go:
package users
import " github.com/abdul-hamid-achik/fuego/pkg/fuego "
// GET /api/users/:id
func Get ( c * fuego . Context ) error {
id := c . Param ( "id" )
return c . JSON ( 200 , map [ string ] any {
"id" : id ,
"name" : "User " + id ,
})
}
// PUT /api/users/:id
func Put ( c * fuego . Context ) error {
id := c . Param ( "id" )
var input struct {
Name string `json:"name"`
}
if err := c . Bind ( & input ); err != nil {
return fuego . BadRequest ( "invalid request body" )
}
return c . JSON ( 200 , map [ string ] any {
"id" : id ,
"name" : input . Name ,
"updated" : true ,
})
}
// DELETE /api/users/:id
func Delete ( c * fuego . Context ) error {
id := c . Param ( "id" )
return c . JSON ( 200 , map [ string ] string {
"message" : "User " + id + " deleted" ,
})
}
Now GET /api/users/123 returns {"id": "123", "name": "User 123"}.
View Your Routes
Output:
Fuego Routes
GET / app/page.templ
GET /api/health app/api/health/route.go
GET /api/users app/api/users/route.go
POST /api/users app/api/users/route.go
GET /api/users/{id} app/api/users/[id]/route.go
PUT /api/users/{id} app/api/users/[id]/route.go
DELETE /api/users/{id} app/api/users/[id]/route.go
Middleware:
/api/* app/api/middleware.go
Total: 7 routes
Build for Production
This compiles everything into a single binary with no external dependencies.
The production binary is typically 10-15MB and includes all static files.
Project Structure
Here’s the full structure after adding routes:
Next Steps