Gotth offers a structured way to serve dynamic UIs with templ, handle all that important HTML metadata, and integrate smoothly with modern frontend tools like Tailwind CSS and HTMX.
"Ship fast, fail fast" - As we all know.
-
gotth.WebServer: Your Web Server Foundation:- A ready-to-go HTTP server. You can easily plug in global middlewares and tell it where your static assets (CSS, JS, images) are.
- Comes with graceful shutdown, because smooth deployments are happy deployments.
- Uses the standard
http.ServeMuxfor routing when you useServeContentdirectly.
-
Define your content with
ContentProviderFunc:- This is how you define what each page shows. A
ContentProviderFuncreturns your page-specific metadata (for the<head>) and the maintempl.Componentfor the body.
- This is how you define what each page shows. A
-
Static File Serving (
StaticAssetFS):- Straightforward configuration for serving your static files (CSS, JavaScript, images).
-
head.HeadViewModel: Comprehensive HTML<head>Management:- Managing the HTML
<head>can be a pain, right?HeadViewModelmakes it much easier. - It uses a clean functional options pattern (those
With...functions) to set things up. - Smart Defaults: It can automatically figure out Open Graph and Twitter card metadata from your basic page info if you don't specify them.
- Supports a Ton of Stuff:
- Core metadata: title, description, canonical URL, keywords, author.
- Icons: Favicons, Apple touch icons.
- Microsoft stuff: MS tile and browser configuration.
- Social Sharing: Open Graph tags (type, locale, URL, title, description, image, etc.) and Twitter Card tags.
- Theming:
theme-color,apple-mobile-web-app-status-bar-style,color-scheme. - Custom Fonts:
FontLinkfor your web fonts. - Stylesheets:
StylesheetLinkwith media, integrity, and crossorigin attributes. - Header Scripts:
ScriptLinkwith async, defer, type, integrity, and crossorigin. - Easy Frontend Libs: Quickly include HTMX, HTMX Preload Extension, and Alpine.js from CDNs (SRI included, and you can use your own URLs) or create your own with Header Scripts.
- Analytics: Just drop in your Google Analytics tag ID.
- Custom Meta Tags: If you need anything else, you can add it.
- Managing the HTML
-
head.JSONLDNode: Structured Data with JSON-LD:- Want to give search engines more detailed info?
JSONLDNodehelps you define JSON-LD objects. - It handles the specific JSON-LD keywords (
@context,@id,@type) and custom properties correctly when marshaling to JSON. - You can add this to your
HeadViewModelusingWithPreparedJSONLD(if you have a pre-made JSON string) orWithJSONLD(to marshal aJSONLDNodeobject directly – note: theWithJSONLDinhead/viewmodel.gois a placeholder and needs full marshaling logic).
- Want to give search engines more detailed info?
-
viewmodel.NewViewModel: Generic ViewModel Builder:- A handy generic function
NewViewModel[T any](data ...ViewModelData[T]) *T. It uses functional options to initialize pretty much any view model struct you define. Less boilerplate is good!
- A handy generic function
-
Session Management (
middlewarespackage):- If you need user sessions, Gotth provides the basics.
SessionStoreinterface: Abstract away your session storage (e.g., database, Redis). You implementExchangeSessionIDForUserandInvalidateSession.SessionCheckmiddleware: Checks for a session cookie, validates it with yourSessionStore, gets the user, and puts the user info into the request context. Can handle required or optional sessions.InvalidateSessionmiddleware: Clears the session from yourSessionStoreand removes the cookie.GetUser(ctx context.Context): A helper to easily get the user from the request context.
-
Example App:
- Check out
example/cmd/main.go. It's a working example showing how to use Gotth withtempl, Tailwind, and HTMX. You'll see:- Server setup.
- Static file serving.
- How to write a
ContentProviderFunc. - Using
HeadViewModel. - Adding custom middleware.
- Site visbile here
- Check out
-
Install:
go get github.com/ancalabrese/gotth
-
Basic Usage:
package main import ( "context" "io" "log" "net/http" "[github.com/a-h/templ](https://github.com/a-h/templ)" "[github.com/ancalabrese/gotth](https://github.com/ancalabrese/gotth)" "[github.com/ancalabrese/gotth/views/components/head](https://github.com/ancalabrese/gotth/views/components/head)" // You'll likely have your own layout package, e.g.: // import "your-project/views/layout" ) // Your page's content provider function func myPageContentProvider(r *http.Request) (head.HeadViewModel, templ.Component, error) { headVM := head.NewHeadViewModel( head.WithPageCoreMetadata("My Page Title", "A cool description of my page.", r.URL.Path), head.WithStylesheet("/static/css/style.css", "", "", ""), head.WithHTMX(""), // Use default HTMX CDN, easy peasy ) // Your page's main content (a templ.Component) pageContent := templ.ComponentFunc(func(ctx context.Context, w io.Writer) error { // This would be a more complex .templ component in a real app _, err := io.WriteString(w, "<div><h1>Welcome!</h1><p>Page content lives here.</p></div>") return err }) return headVM, pageContent, nil } // A simplified layout component example // In a real app, this would be a proper templ component rendering <html>, <head>, <body>, etc. func basicLayout(headVM head.HeadViewModel, content templ.Component) templ.Component { return templ.ComponentFunc(func(ctx context.Context, w io.Writer) error { log.Println("Rendering basic layout with title:", headVM.Core.Title) // Example of using headVM return content.Render(ctx, w) }) } func main() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Setup static asset serving staticFS := gotth.NewStaticAssetFS("/static", http.Dir("./path/to/your/static/files")) // Update this path! cfg := gotth.WebServerConfig{ StaticAssetsFS: []gotth.StaticAssetFS{staticFS}, // Add any global middlewares here: // GlobalMiddlewares: []func(http.Handler) http.Handler{ /* your middleware */ }, } httpServer := &http.Server{ Addr: ":8080", } webServer, err := gotth.New(cfg, httpServer) if err != nil { log.Fatalf("Failed to create web server: %v", err) } // Register your page handler webServer.ServeContent("/my-page", myPageContentProvider) log.Println("Server starting on http://localhost:8080 ✨") if err := webServer.Start(ctx); err != nil { log.Fatalf("Server failed to start: %v", err) } }
ContentProviderFunc: This is central to how Gotth organizes page generation. It keeps your page-specific data and component logic separate from routing.head.HeadViewModel: A structured way to build your HTML<head>. Good for SEO, social sharing, and managing your assets.- Functional Options: You'll see this pattern a lot (e.g.,
With...functions). It makes configuring components cleaner and more explicit. - Middleware: Use global server middleware or the provided session middleware to build up your request processing.
templIntegration: Gotth is built to work hand-in-hand withtemplfor server-side rendering your HTML.
Gotth currently uses http.ServeMux internally. However, the core page rendering logic (ContentProviderFunc, HeadViewModel) is designed to be adaptable. You could make it work with other routers like chi or gorilla/mux by:
- Creating a function that takes your
ContentProviderFunc(and maybe a layout function) and returns a standardhttp.HandlerFunc. - Registering these handlers with your router of choice.
- Exposing the static file serving as an
http.Handlertoo.
This would make Gotth more flexible for different Go web project setups.
Contributions are welcome! Please open an issue to discuss bigger changes or submit a pull request for fixes and small improvements.