Skip to main content
If you’ve used modern meta-frameworks like Next.js, Nuxt, SvelteKit, or Remix, Fuego’s conventions will feel natural.

Quick Comparison

ConceptOther FrameworksFuego
Route fileroute.ts / +server.tsroute.go
Page filepage.tsx / +page.sveltepage.templ
Layoutlayout.tsx / +layout.sveltelayout.templ
Middlewaremiddleware.tsmiddleware.go
Dynamic segment[id][id]
Catch-all[...slug][...slug]
Optional catch-all[[...slug]][[...slug]]
Route groups(group)(group)

Key Differences

Handlers Are Named After HTTP Methods

In JavaScript frameworks, you export named functions like GET, POST, etc. In Fuego, you define functions with capitalized method names:
// app/api/users/route.go
package users

import "github.com/abdul-hamid-achik/fuego/pkg/fuego"

func Get(c *fuego.Context) error {
    return c.JSON(200, []string{"alice", "bob"})
}

func Post(c *fuego.Context) error {
    var user User
    if err := c.Bind(&user); err != nil {
        return fuego.BadRequest("invalid input")
    }
    return c.JSON(201, user)
}

func Put(c *fuego.Context) error { /* ... */ }
func Patch(c *fuego.Context) error { /* ... */ }
func Delete(c *fuego.Context) error { /* ... */ }

Templates Use templ, Not JSX

Instead of JSX/TSX, Fuego uses templ for type-safe HTML:
// app/dashboard/page.templ
package dashboard

templ Page() {
    <div class="container">
        <h1>Dashboard</h1>
        <p>Welcome back!</p>
    </div>
}
Templ provides:
  • Compile-time type checking
  • No runtime template parsing
  • Go code completion in templates
  • Smaller binary size than text/template

No Build Step for Go Code

Unlike JavaScript frameworks that require bundling, Fuego compiles to a single binary:
# Development
fuego dev

# Production
fuego build
./myapp
The binary includes everything - no need for node_modules, npm, or a separate build step for your Go code.

HTMX Instead of Client-Side Frameworks

For interactivity, Fuego encourages HTMX over React/Vue/Svelte:
<!-- Load data on page load -->
<div hx-get="/api/users" hx-trigger="load">
    Loading...
</div>

<!-- Submit form without page reload -->
<form hx-post="/api/users" hx-target="#user-list">
    <input name="name" />
    <button type="submit">Add User</button>
</form>
Benefits:
  • No JavaScript to write
  • Server renders HTML
  • Smaller page weight
  • Works with any backend

Migration Patterns

From Next.js App Router

Next.jsFuego
app/api/users/route.tsapp/api/users/route.go
export async function GET()func Get(c *fuego.Context) error
NextRequest*fuego.Context
NextResponse.json()c.JSON(status, data)
NextResponse.redirect()c.Redirect(status, url)
cookies().get()c.Cookie("name")
headers().get()c.Header("name")

From Nuxt

NuxtFuego
server/api/users.tsapp/api/users/route.go
defineEventHandler()func Get(c *fuego.Context) error
getQuery(event)c.Query("key")
readBody(event)c.Bind(&body)
setResponseStatus()c.JSON(status, data)

From SvelteKit

SvelteKitFuego
+server.tsroute.go
+page.sveltepage.templ
+layout.sveltelayout.templ
RequestHandlerfunc Get(c *fuego.Context) error
json() helperc.JSON(status, data)

File Structure Comparison

JavaScript Framework (Next.js style)

Fuego

The structure is nearly identical - just swap the file extensions.

Code Comparison

// app/api/users/route.ts
import { NextRequest, NextResponse } from 'next/server'

export async function GET(request: NextRequest) {
  const users = await db.users.findMany()
  return NextResponse.json(users)
}

export async function POST(request: NextRequest) {
  const body = await request.json()
  const user = await db.users.create({ data: body })
  return NextResponse.json(user, { status: 201 })
}

Why Go?

If you’re comfortable with JavaScript frameworks, why use Fuego?
BenefitDescription
PerformanceGo is significantly faster than Node.js for CPU-bound tasks
MemoryLower memory footprint, important for containers
Type safetyCompile-time checks catch errors early
DeploymentSingle binary, no runtime dependencies
ConcurrencyGoroutines handle concurrent requests efficiently
SimplicityNo package manager drama, stable stdlib

Next Steps