Rethinking SaaS Stacks: Why I’m Trying Go Instead of NextJS
Rethinking SaaS Stacks: Why I’m Trying Go Instead of NextJS

Hey friends,
This past week, I found myself tinkering with an idea that’s been sitting in the back of my mind for a while:
"What if I tried building a SaaS app in Go instead of NextJS?"
Let’s be clear, it’s not the most “productive” move.
I’ve spent the past couple of years pretty deep in the NextJS/TypeScript ecosystem, and I’m comfortable there.
But sometimes curiosity wins. And honestly? I like showing what it’s like to start something from scratch, especially when it means challenging your defaults.
So this is me exploring the idea of a new stack, something called the GOAT stack: Go + AlpineJS + Templ.
Let me walk you through the thinking.
Why Golang?
First, Golang (created by Google) was designed to solve specific issues Google encountered in other programming languages while building their services.
As a result, Go is actively maintained, frequently updated, and rapidly growing.
Key advantages:
-
Compiled & Fast: Compiles quickly into efficient binaries, resulting in fast startup times, better scalability, easy Dockerization, and improved SEO from quicker page loads.
-
Strongly Typed: Typed languages introduce friction, but greatly enhance readability, maintainability, and integration with AI coding assistants.
-
Clear Syntax: Simple and readable code.
-
Efficient Concurrency: Easy implementation of concurrent tasks and asynchronous functions.
Additionally, as someone with a backend-focused background, I've found server-side rendering with Go simpler and lighter than with NextJS.
The GOAT Stack
The GOAT stack leans into that clarity.
-
Go handles the backend and rendering
-
Templ is a type-safe HTML templating engine built for Go
-
AlpineJS adds just enough interactivity on the frontend without dragging in a huge JS framework
In other words, it’s intentionally not a React-based SPA. It’s backend-first, minimal, and refreshingly old-school, but modernized in the right places.
That might not be everyone’s cup of tea.
But I wanted to see how far you can get building a SaaS without leaning on the usual React + Next + client-heavy stack.
Templ: Type-safe templates with Go
Templ lets you write HTML using Go syntax.
Think reusable components, logic in templates, and compile-time safety. It’s elegant, especially if you’re already in the Go mindset.
One of the things I missed in Go was a first-class way to render views. Templ fills that gap perfectly.
AlpineJS: Just enough frontend
Sometimes you just need a button that toggles a div. Or a form that shows a loader. Not everything needs React, state management libraries, and hydration strategies.
AlpineJS is like modern-day jQuery, but much more elegant. It lets you interact in your HTML with declarative syntax. That’s a perfect fit for server-rendered pages.
Example AlpineJS Usage:
<div x-data="{ open: false }">
<button @click="open = !open">Toggle</button>
<div x-show="open">Content...</div>
</div>

Setting it up
Here's a concise setup guide:
1. Prerequisites
To set up your development environment for the GOAT stack, you'll need to install Go, Templ, and Make. Here are the official sources where you can find installation instructions for each:
- Go Installation Guide: https://go.dev/doc/install
- Templ Installation Guide: https://templ.guide/quick-start/installation/
- Make Installation Guide for MacOS:
brew install make
2. Initialize Your Project
mkdir goat-project
cd goat-project
export GO_MODULE_PATH="github.com/yourusername/goat-project"
go mod init ${GO_MODULE_PATH}
3. Install Templ
go get github.com/a-h/templ
4. Project Structure
Organize your directories:
goat-project/
├── .gitignore
├── .env
├── go.mod
├── main.go
├── Makefile
├── internal/
│ ├── api/
│ ├── components/
│ ├── config/
│ ├── db/
│ ├── handlers/
│ ├── models/
│ └── pages/
│ ├── home.templ
│ └── layout.templ
├── secure/
└── static/
5. Makefile
Simplify build, run, and development tasks:
.PHONY: build run clean
build:
templ generate
go build -o bin/main .
run: build
./bin/main
dev:
templ generate --watch --cmd="go run main.go"
clean:
rm -rf bin/
rm -f *_templ.go
6. Templ Layout Example
Create layout.templ
in internal/pages
:
package pages
templ Layout(children ...templ.Component) {
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>GOAT Project</title>
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
<script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
</head>
<body>
<div class="pt-16">
for _, child := range children {
@child
}
</div>
</body>
</html>
}
7. Basic Page (home.templ
)
package pages
templ main() {
<div x-data="{ open: false }">
<button @click="open = !open">Toggle</button>
<div x-show="open">Hello World</div>
</div>
}
templ Home() {
@Layout(main())
}
8. Your Go Server (main.go
)
package main
import (
"log"
"net/http"
"os"
"github.com/yourusername/goat-project/internal/pages"
"github.com/a-h/templ"
)
func main() {
log.Println("Starting server...")
homePage := pages.Home()
mux := http.NewServeMux()
mux.Handle("/", templ.Handler(homePage))
port := os.Getenv("PORT")
if port == "" {
port = "5050"
log.Printf("Defaulting to port %s", port)
}
log.Printf("Server starting on port %s", port)
log.Fatal(http.ListenAndServe(":"+port, mux))
}
9. Running Your Project
Start the development server:
make dev
Visit http://localhost:5050 to see your page. Click on the button you should see the “Hello Word" text appear.
This guide provides a strong foundation for building SaaS apps with Go, AlpineJS, and Templ. Happy coding!
See you next week !