Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

go-web-core

CI

Reusable Go web foundation for server-rendered applications.

go-web-core provides the common infrastructure I use across Go web projects so new applications can start with a tested foundation instead of rebuilding the same plumbing each time.

It is intentionally small and does not include application-specific features such as authentication, users, clients, projects, billing, or business logic.

Features

  • Environment-based application configuration
  • SQLite database setup
  • Automatic database directory creation
  • SQLite foreign-key enforcement
  • SQL migration runner
  • Migration tracking
  • Structured logging with log/slog
  • HTTP request logging middleware
  • Health endpoint
  • HTML template rendering
  • HTMX-aware redirects
  • Generic form validation helpers
  • Automated tests for core behaviour

Installation

go get github.com/danieljmanningdev/go-web-core

Packages

config

Loads common application configuration from environment variables.

cfg := config.Load()

Supported variables:

APP_ENV
APP_PORT
LOG_LEVEL
DATABASE_PATH
TEMPLATE_DIR

Default values:

APP_ENV=development
APP_PORT=8080
LOG_LEVEL=info
DATABASE_PATH=./data/app.db
TEMPLATE_DIR=web/templates

database

Provides SQLite database setup and migration support.

db, err := database.Open(ctx, cfg.DatabasePath)
if err != nil {
	log.Fatal(err)
}
defer db.Close()

Run SQL migrations from a directory:

if err := database.RunMigrations(db.SQL, "migrations"); err != nil {
	log.Fatal(err)
}

Migration files use numbered filenames:

001_initial.sql
002_users.sql
003_projects.sql

Applied migrations are recorded in the schema_migrations table.


logging

Creates a structured slog.Logger.

logger := logging.New(
	cfg.Environment,
	cfg.LogLevel,
)

Development environments use text logs.

Production uses JSON logs.


middleware

Provides reusable HTTP middleware.

handler := middleware.RequestLogger(
	logger,
	mux,
)

The request logger records:

  • HTTP method
  • request path
  • response status
  • request duration

health

Provides a simple health endpoint.

mux.HandleFunc("/health", health.HealthHandler)

Response:

{
  "status": "ok"
}

rendering

Provides server-side HTML rendering using Go's html/template.

renderer, err := rendering.New(
	"web/templates/layout.html",
	"web/templates/page.html",
)
if err != nil {
	log.Fatal(err)
}

Render a template:

err = renderer.HTML(
	w,
	http.StatusOK,
	"page",
	data,
)

Templates are rendered into a buffer before the HTTP response is written so template execution errors do not result in partially written pages.

Redirects

Standard request:

rendering.Redirect(
	w,
	r,
	"/dashboard",
	http.StatusSeeOther,
)

HTMX requests automatically receive an HX-Redirect response.


validation

Provides generic validation helpers suitable for forms and request data.

errors := validation.Errors{}

if !validation.Required(name) {
	errors.Add("name", "Name is required.")
}

if !validation.Email(email) {
	errors.Add("email", "Enter a valid email address.")
}

if !validation.MaxLength(name, 100) {
	errors.Add("name", "Name must be 100 characters or fewer.")
}

if !validation.OneOf(status, "active", "inactive") {
	errors.Add("status", "Invalid status.")
}

if errors.Any() {
	// Return validation errors.
}

Available helpers include:

Required
MinLength
MaxLength
Email
OneOf

Example

A minimal application could look like:

package main

import (
	"context"
	"fmt"
	"log"
	"net/http"

	"github.com/danieljmanningdev/go-web-core/config"
	"github.com/danieljmanningdev/go-web-core/database"
	"github.com/danieljmanningdev/go-web-core/health"
	"github.com/danieljmanningdev/go-web-core/logging"
	"github.com/danieljmanningdev/go-web-core/middleware"
)

func main() {
	cfg := config.Load()

	logger := logging.New(
		cfg.Environment,
		cfg.LogLevel,
	)

	db, err := database.Open(
		context.Background(),
		cfg.DatabasePath,
	)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	if err := database.RunMigrations(
		db.SQL,
		"migrations",
	); err != nil {
		log.Fatal(err)
	}

	mux := http.NewServeMux()

	mux.HandleFunc(
		"/health",
		health.HealthHandler,
	)

	handler := middleware.RequestLogger(
		logger,
		mux,
	)

	logger.Info(
		"server starting",
		"port",
		cfg.Port,
	)

    address := fmt.Sprintf(":%d", cfg.Port)

    if err := http.ListenAndServe(
        address,
        handler,
    ); err != nil {
        log.Fatal(err)
    }
}

Design philosophy

This project is deliberately a web core rather than a full framework.

It contains infrastructure that is useful across many Go applications while leaving domain-specific functionality to individual projects or separate modules.

Features such as authentication, sessions, CSRF protection, client management, project management, contracts, billing, and application-specific UI should remain separate unless they become fundamental dependencies of nearly every application.

The goal is simple:

Start every Go web project with a small, tested and familiar foundation.

Development

Format the code:

gofmt -w .

Run the test suite:

go test ./...

Run static analysis:

go vet ./...

Check whitespace errors:

git diff --check

Status

The project is currently in early development.

Until the API stabilises, releases should be considered pre-v1.0.0 and may contain breaking changes.

License

See LICENSE.

About

Reusable Go web foundation for server-rendered applications with SQLite, migrations, logging, middleware, rendering, HTMX redirects, and validation.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages