DEV Community

Cover image for Build Faster Web Apps with GoWeb Template
Mahmoud Ehab
Mahmoud Ehab

Posted on

Build Faster Web Apps with GoWeb Template

This blog has been 99% generated by AI (MiniMax m2.5).

You don't need React to build a great web app. Most web applications are fundamentally simple—display data, process forms, handle auth. Yet we're shipping megabytes of JavaScript and waiting for client-side hydration just to render a login form.

There's a better way.

Why Go + HTMX Beats NextJS

Zero JavaScript Compilation

HTMX sends HTML over the wire. That's it. No React, no virtual DOM, no hydration. You write your UI once on the server and the browser just displays it. The entire HTMX library is 14KB. Your NextJS bundle? Much, much larger.

This isn't about going backwards. It's about using the right tool. For most web apps, the "progressive enhancement" approach is faster to build, faster to load, and easier to maintain.

Real Go, No TypeScript

With Go + HTMX, you write Go everywhere. Your backend is Go. Your templates are Go (via Templ). Your validation is Go. You don't need to switch contexts between Go, TypeScript, and SQL.

NextJS demands you learn the React ecosystem—their router, their data fetching, their server components, their edge runtime. Go Fiber gives you one router, one pattern, one language.

Blazing Fast Performance

Go Fiber is built on top of fasthttp, which is significantly faster than the standard library. Benchmarks show Fiber handling more requests per second than most Go routers. Combined with server-rendered HTML, your pages load instantly—no client-side waterfall, no loading spinners.

Smaller Attack Surface

No client-side JavaScript bundle means fewer security concerns. No XSS from React's dangerouslySetHTML (you're just sending HTML). No exposed API endpoints to secure on the client. Your app is simpler and harder to attack.

The Stack

GoWeb gives you a complete, modern stack:

  • Go Fiber — Fast HTTP router
  • Templ — Type-safe Go templates that compile to HTML
  • HTMX — Progressive enhancement for interactivity
  • Tailwind — Utility-first CSS
  • GORM + Goose — Database ORM and migrations
  • PostgreSQL — Rock-solid relational database

Everything wires together cleanly with a directory structure that scales: handlers/ for HTTP logic, db/ for data access, ui/ for components.

Checkout the template on GitHub: https://github.com/mmoehabb/goweb-template

Code Example: Adding a Feature

Let's see how easy it is to add user registration. First, define your model:

// db/users/model.go
type User struct {
    ID        uint   `gorm:"primaryKey"`
    Username  string `gorm:"uniqueIndex;not null"`
    Password  string `gorm:"not null"`
    CreatedAt time.Time
}

func (User) TableName() string { return "users" }
Enter fullscreen mode Exit fullscreen mode

Add a query function:

// db/users/queries.go
func Add(u User) error {
    return db.Connection.Create(&u).Error
}
Enter fullscreen mode Exit fullscreen mode

Write the handler:

// handlers/user/register.go
func Register(c fiber.Ctx) error {
    var input struct {
        Username string `json:"username"`
        Password string `json:"password"`
    }
    if err := c.BodyParser(&input); err != nil {
        return c.Status(400).SendString("invalid input")
    }

    hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(input.Password), 14)
    user := User{Username: input.Username, Password: string(hashedPassword)}
    if err := users.Add(user); err != nil {
        return c.Status(400).SendString("username taken")
    }

    return c.Redirect("/login")
}
Enter fullscreen mode Exit fullscreen mode

Build the form with Templ:

// ui/forms/register.templ
package forms

templ Register() {
    <form method="POST" action="/register" class="space-y-4">
        <div>
            <label class="block text-sm font-medium">Username</label>
            <input type="text" name="username" class="mt-1 block w-full rounded border-gray-300" />
        </div>
        <div>
            <label class="block text-sm font-medium">Password</label>
            <input type="password" name="password" class="mt-1 block w-full rounded border-gray-300" />
        </div>
        <button type="submit" class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700">
            Register
        </button>
    </form>
}
Enter fullscreen mode Exit fullscreen mode

Register the route in main.go:

app.Post("/register", user.Register)
Enter fullscreen mode Exit fullscreen mode

That's it. Type-safe templates, compile-time checks, full Go types, no client-side JavaScript. Five files, no build steps.

Getting Started

git clone https://github.com/mmoehabb/goweb-template && cd goweb-template
go install github.com/mmoehabb/luci@latest
luci install
luci dev
Enter fullscreen mode Exit fullscreen mode

Visit http://localhost:3000. You'll see a working login and registration system ready to extend.

The Bottom Line

If you want simplicity without sacrificing power, GoWeb delivers. You get a fast backend, type-safe templates, and progressive enhancement—all with one language and zero JavaScript bundles.

NextJS is great for complex SPAs. But most of us are building CRUD apps. Give GoWeb Template a try—you might never go back.

Top comments (0)