A modern, production-ready full-stack template using Htmx, Go, and PostgreSQL.
Build dynamic web applications without JavaScript frameworks. Use Htmx for interactivity, Go for a fast backend, and PostgreSQL for data persistence. No build step, no bundlers, just pure simplicity.
- π― Htmx - Dynamic UI without JavaScript frameworks
- π΅ Go - Fast, compiled backend with Chi router
- π PostgreSQL - Reliable, production-ready database
- π¨ Tailwind CSS - Beautiful styling via CDN
- π³ Docker Optimized - Multi-stage builds for small images
- π Railway Ready - Zero-config deployment
- β‘ No Build Step - Just code and deploy
- π CRUD Example - Working todo list included
Click the "Deploy on Railway" button above. Railway will automatically:
- Build your Go application using Docker
- Provision a PostgreSQL database
- Connect them together
- Generate a public URL
Prerequisites:
- Go 1.21 or higher
- PostgreSQL (or use Docker)
Steps:
# Clone the repository
git clone https://github.com/YOUR_USERNAME/htmx-go-postgres.git
cd htmx-go-postgres
# Install dependencies
go mod download
# Set up PostgreSQL (or use Docker)
docker run --name postgres -e POSTGRES_PASSWORD=postgres -p 5432:5432 -d postgres
# Set environment variables
export DATABASE_URL="postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable"
export PORT=8080
# Run the application
go run cmd/web/main.go
# Open browser to http://localhost:8080htmx-go-postgres/
βββ cmd/
β βββ web/
β βββ main.go # Application entry point
βββ templates/
β βββ index.html # Main page
β βββ todo-list.html # Todo list partial
βββ static/
β βββ css/ # Custom CSS (optional)
β βββ js/ # Custom JS (optional)
βββ Dockerfile # Multi-stage Docker build
βββ railway.toml # Railway configuration
βββ go.mod # Go dependencies
βββ go.sum # Go checksums
βββ README.md # Documentation
Htmx allows you to build dynamic UIs using HTML attributes:
<!-- Add a todo -->
<form hx-post="/todos"
hx-target="#todo-list"
hx-swap="innerHTML">
<input type="text" name="title" required>
<button type="submit">Add</button>
</form>
<!-- Toggle completed -->
<input type="checkbox"
hx-put="/todos/123/toggle"
hx-target="#todo-list">
<!-- Delete a todo -->
<button hx-delete="/todos/123"
hx-target="#todo-list"
hx-confirm="Delete this?">
Delete
</button>No JavaScript required! Htmx handles all the AJAX calls and DOM updates.
Simple, fast Go server with Chi router:
// Create todo
r.Post("/todos", app.createTodo)
// Toggle todo
r.Put("/todos/{id}/toggle", app.toggleTodo)
// Delete todo
r.Delete("/todos/{id}", app.deleteTodo)Returns HTML fragments that Htmx swaps into the page.
Simple schema with auto-migration:
CREATE TABLE todos (
id SERIAL PRIMARY KEY,
title TEXT NOT NULL,
completed BOOLEAN DEFAULT FALSE
);Edit cmd/web/main.go:
// Add your route
r.Get("/mypage", app.myPageHandler)
// Create handler
func (app *Application) myPageHandler(w http.ResponseWriter, r *http.Request) {
app.Templates.ExecuteTemplate(w, "mypage.html", data)
}Create templates/mypage.html:
<div>
<h1>My Page</h1>
<p>Content here...</p>
</div>Extend the schema in main.go:
func createTable(db *sql.DB) {
query := `
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL
);
`
db.Exec(query)
}Use Tailwind classes inline, or add custom CSS in static/css/.
- β Complex build toolchains
- β Large JavaScript bundles
- β State management hell
- β SEO challenges
- β Slow initial load
- β No Build Step - Write HTML and Go
- β Small Payload - Htmx is ~14KB
- β Server-Side Rendering - SEO-friendly by default
- β Progressive Enhancement - Works without JS
- β Simple Mental Model - Just HTML attributes
- β Fast - No client-side framework overhead
- Htmx Documentation - Official Htmx docs
- Htmx Examples - Real-world examples
- Hypermedia Systems - Book on Htmx architecture
- Go Documentation - Official Go docs
- Chi Router - Lightweight Go router
- Go by Example - Hands-on Go tutorials
- Railway Docs - Platform documentation
- PostgreSQL on Railway - Database guide
π Internal Dashboards - Admin panels, monitoring tools
π Content-Heavy Sites - Blogs, documentation, news sites
π οΈ CRUD Applications - Data management, forms, tables
π’ Business Applications - CRM, inventory, invoicing
π± Progressive Enhancement - Works without JavaScript
β Real-time collaboration (use WebSockets instead)
β Heavy client-side state (use React/Vue)
β Offline-first apps (use PWA/WASM)
β Complex animations (use JavaScript)
- Server Response: < 50ms (Go is fast!)
- Page Load: Minimal (no framework to download)
- Bundle Size: ~14KB (just Htmx + Tailwind CDN)
- Memory Usage: ~20-30MB (Go binary)
- Database Queries: Optimized with indexes
- β SQL injection protected (parameterized queries)
- β CSRF protection (add middleware if needed)
- β XSS protection (Go templates auto-escape)
- β HTTPS on Railway (automatic SSL)
Contributions welcome! Here's how:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing) - Open a Pull Request
MIT License - see LICENSE file for details
Built with β€οΈ for the Railway community π
Tired of JavaScript complexity? This template proves you don't need React/Vue/Angular for dynamic UIs!
Questions? Open an issue on GitHub or reach out on Railway Discord.