goapplib

package module
v0.7.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 6, 2026 License: Apache-2.0 Imports: 17 Imported by: 5

README

goapplib

A Go library for server-rendered web apps, with islands of client code (@panyam/tsappkit, @panyam/tsappkit-solid) and Go handlers that can run in the browser as wasm (wasmhost).

The docs are at https://panyam.github.io/goapplib/, built from docsite/: a getting-started guide, guides for each part with live demos, and the Go API generated from the source on main. SUMMARY.md is a tour of this repo.

Documentation

Index

Constants

View Source
const (
	ColorReset  = "\033[0m"
	ColorCyan   = "\033[36m"
	ColorGreen  = "\033[32m"
	ColorYellow = "\033[33m"
	ColorBold   = "\033[1m"
)

ANSI color codes

Variables

This section is empty.

Functions

func CORS

func CORS(next http.Handler) http.Handler

CORS adds CORS headers for local development.

func DefaultFuncMap

func DefaultFuncMap() template.FuncMap

DefaultFuncMap returns the default template functions.

func DefaultRateLimitKeyFunc

func DefaultRateLimitKeyFunc(r *http.Request) string

DefaultRateLimitKeyFunc extracts the client identifier from the request. Uses X-Forwarded-For for proxied requests, otherwise RemoteAddr.

func GetLocalIP

func GetLocalIP() (string, error)

GetLocalIP returns the local network IP address (preferring ethernet/wifi over localhost)

func GzipFileServer

func GzipFileServer(root http.FileSystem) http.Handler

GzipFileServer wraps an http.Handler to serve pre-compressed .gz files when available and the client accepts gzip encoding.

For WASM files, this serves .wasm.gz (4.7MB) instead of .wasm (25MB), reducing transfer size by ~81%.

func HtmxCurrentURL

func HtmxCurrentURL(r *http.Request) string

HtmxCurrentURL returns the HX-Current-URL header value.

func HtmxPrompt

func HtmxPrompt(r *http.Request) string

HtmxPrompt returns the HX-Prompt header value.

func HtmxTarget

func HtmxTarget(r *http.Request) string

HtmxTarget returns the HX-Target header value.

func HtmxTrigger

func HtmxTrigger(r *http.Request) string

HtmxTrigger returns the HX-Trigger header value.

func IsBoostedRequest

func IsBoostedRequest(r *http.Request) bool

IsBoostedRequest checks if the request is a boosted link.

func IsHtmxRequest

func IsHtmxRequest(r *http.Request) bool

IsHtmxRequest checks if the request is an HTMX request.

func LoadAll

func LoadAll(r *http.Request, w http.ResponseWriter, app any, loaders ...Loader) (error, bool)

LoadAll runs loaders in order with the page's app, and stops at the first one that returns an error or finished = true, returning what it returned. A nil loader is skipped. A page typically calls it from its own Load:

func (p *GamesPage) Load(r *http.Request, w http.ResponseWriter, app *goapplib.App[*Site]) (error, bool) {
	return goapplib.LoadAll(r, w, app, &p.BasePage, &p.WithPagination, goapplib.LoaderFunc[*Site](p.loadGames))
}

func ParseTemplateSpec

func ParseTemplateSpec(spec string) (fileName, blockName string)

ParseTemplateSpec parses a template spec into file name and block name. Format: "path/to/template" or "path/to/template:BlockName"

If no ":" is present, block name is auto-derived from the base filename. If ":" is present, the part after ":" is used as the explicit block name. An empty block name after ":" means render the entire template file.

func PrintStartupMessage

func PrintStartupMessage(address string)

PrintStartupMessage prints a colorized startup message with clickable links

func Register

func Register[V View[AC], AC any](
	app *App[AC],
	mux *http.ServeMux,
	pattern string,
	opts ...Option,
) *http.ServeMux

Register registers a View at the given pattern. If mux is nil, a new ServeMux is created. Returns the mux for chaining.

Usage:

mux := http.NewServeMux()
goapplib.Register[*HomePage](app, mux, "/")
goapplib.Register[*GameListingPage](app, mux, "/games/")

func RegisterFunc

func RegisterFunc(
	mux *http.ServeMux,
	pattern string,
	handler http.HandlerFunc,
) *http.ServeMux

RegisterFunc registers a handler function at the given pattern. Convenience wrapper for mux.HandleFunc.

func RegisterGroup

func RegisterGroup[G PageGroup[AC], AC any](
	app *App[AC],
	mux *http.ServeMux,
	prefix string,
	opts ...Option,
) *http.ServeMux

RegisterGroup registers a PageGroup under the given prefix. The group's routes are mounted with the prefix stripped.

Usage:

goal.RegisterGroup[*GamesGroup](app, rootMux, "/games")

func RegisterHandler

func RegisterHandler(
	mux *http.ServeMux,
	pattern string,
	handler http.Handler,
) *http.ServeMux

RegisterHandler registers an http.Handler at the given pattern. Convenience wrapper for mux.Handle.

func SetupTemplates

func SetupTemplates(paths ...string) *tmplr.TemplateGroup

SetupTemplates creates a TemplateGroup with the given paths. Paths are checked in order, so put your app's templates first for overrides.

func SmartRegister

func SmartRegister[V interface {
	View[AC]
	HtmxAware
}, AC any](
	app *App[AC],
	mux *http.ServeMux,
	pattern string,
	fullTemplateSpec string,
	fragmentTemplateSpec string,
	opts ...Option,
) *http.ServeMux

SmartRegister registers a View that renders fullTemplateSpec as a page and fragmentTemplateSpec for an htmx request that wants a fragment. It's Register with WithTemplate(fullTemplateSpec) and WithFragmentTemplate(fragmentTemplateSpec), kept for the code that calls it; new code can pass WithFragmentTemplate to Register or MuxBuilder.Page directly.

Types

type App

type App[AppContext any] struct {
	Context            AppContext
	Templates          *tmplr.TemplateGroup
	RenderTemplateFunc func(w http.ResponseWriter, templateFileName string, templateBlockName string, view any) error
}

App holds app-level shared state and template system. AppContext is the application context type defined by your application (e.g., *WeewarApp).

func NewApp

func NewApp[AppContext any](ctx AppContext, templates *tmplr.TemplateGroup) *App[AppContext]

NewApp creates a new App with the given application context and templates.

func (*App[AppContext]) NewMux

func (app *App[AppContext]) NewMux() *MuxBuilder[AppContext]

NewMux creates a MuxBuilder for fluent route building.

func (*App[AppContext]) RenderTemplate

func (app *App[AppContext]) RenderTemplate(
	w http.ResponseWriter,
	templateFileName string,
	templateBlockName string,
	view any) error

RenderTemplate renders the named template with the given view data. The page is rendered in full before any of it is written, so on an error nothing has reached w and the caller can still answer with an error status (#108). If RenderTemplateFunc is set, it delegates to that function, which is responsible for its own writes.

type AuthProvider

type AuthProvider interface {
	GetLoggedInUserId(r *http.Request) string
	GetUserById(id string) (AuthUser, error)
}

AuthProvider is the interface for auth services.

type AuthUser

type AuthUser interface {
	Profile() map[string]any
}

AuthUser is a minimal user interface.

type BasePage

type BasePage struct {
	Title               string // Page title (internal use, fallback for MetaTitle)
	BodyClass           string // CSS classes for <body>
	ActiveTab           string // Highlight active navigation tab
	CustomHeader        bool   // If true, skip default header rendering
	DisableSplashScreen bool   // If true, hide loading splash
	SplashTitle         string // Custom splash title
	SplashMessage       string // Custom splash message
	BodyDataAttributes  string // HTML data attributes for body

	// SEO fields
	MetaTitle       string // Title for <title> tag and search results (falls back to Title if empty)
	MetaDescription string // Meta description for search engines
	CanonicalUrl    string // Canonical URL for SEO (e.g., https://example.com/page/)
}

BasePage provides common page metadata. Embed this in your page structs.

func (*BasePage) Load

func (p *BasePage) Load(r *http.Request, w http.ResponseWriter, vc any) (error, bool)

Load implements Loader for BasePage. Note: This is a generic implementation that works with any ViewContext.

type EntityListingData

type EntityListingData[ItemType any] struct {
	// Page header
	Title       string
	Subtitle    string
	CreateUrl   string
	CreateLabel string

	// View configuration
	ViewMode           string // "grid" or "list"
	ViewModeStorageKey string // localStorage key for saving preference
	EnableViewToggle   bool
	GridContainerId    string
	SearchInputId      string
	SortSelectId       string
	SearchPlaceholder  string

	// URL "formats".  To get the Url we would do something like fmt.Sprintf(fmt, Id)
	ViewUrlFormat   string
	EditUrlFormat   string
	DeleteUrlFormat string
	SearchUrl       string
	RefreshUrl      string

	// Sort options
	SortOptions []SortOption

	// Items to display - templates access fields directly (e.g., .Id, .Name, .Description)
	Items []ItemType

	// Actions
	ShowActions    bool
	ShowEditButton bool // Show edit button (typically only when logged in)
	HtmxEnabled    bool
	RefreshTrigger string

	// Empty state
	EmptyTitle   string
	EmptyMessage string
}

EntityListingData provides data for the EntityListing template component. This struct is designed to work with the EntityListing.html template. ItemType is the type of items in the listing - templates access item fields directly (e.g., .Id, .Name).

func NewEntityListingData

func NewEntityListingData[ItemType any](title string, viewUrlFormat string) *EntityListingData[ItemType]

NewEntityListingData creates a new EntityListingData with sensible defaults.

func (*EntityListingData[ItemType]) DeleteUrl

func (d *EntityListingData[ItemType]) DeleteUrl(id string) string

Returns the formatted DeleteUrl

func (*EntityListingData[ItemType]) EditUrl

func (d *EntityListingData[ItemType]) EditUrl(id string) string

Returns the formatted EditUrl

func (*EntityListingData[ItemType]) ViewUrl

func (d *EntityListingData[ItemType]) ViewUrl(id string) string

Returns the formatted ViewUrl

func (*EntityListingData[ItemType]) WithCreate

func (d *EntityListingData[ItemType]) WithCreate(url, label string) *EntityListingData[ItemType]

WithCreate sets the create URL and label

func (*EntityListingData[ItemType]) WithDelete

func (d *EntityListingData[ItemType]) WithDelete(url string) *EntityListingData[ItemType]

WithDelete sets the delete URL

func (*EntityListingData[ItemType]) WithEdit

func (d *EntityListingData[ItemType]) WithEdit(url string) *EntityListingData[ItemType]

WithEdit sets the edit URL

func (*EntityListingData[ItemType]) WithHtmx

func (d *EntityListingData[ItemType]) WithHtmx(searchUrl string) *EntityListingData[ItemType]

WithHtmx enables HTMX for the listing

func (*EntityListingData[ItemType]) WithView

func (d *EntityListingData[ItemType]) WithView(url string) *EntityListingData[ItemType]

WithView sets the viewer URL

type HtmxAware

type HtmxAware interface {
	ShouldRenderFragment() bool
}

HtmxAware is implemented by views that can detect HTMX requests.

type HtmxResponse

type HtmxResponse struct {
	// contains filtered or unexported fields
}

HtmxResponse provides helpers for setting HTMX response headers.

func NewHtmxResponse

func NewHtmxResponse(w http.ResponseWriter) *HtmxResponse

NewHtmxResponse creates a new HtmxResponse wrapper.

func (*HtmxResponse) Location

func (h *HtmxResponse) Location(url string) *HtmxResponse

Location does a client-side redirect without full page reload.

func (*HtmxResponse) LocationWithContext

func (h *HtmxResponse) LocationWithContext(spec map[string]any) *HtmxResponse

LocationWithContext does a redirect with additional context.

func (*HtmxResponse) PushURL

func (h *HtmxResponse) PushURL(url string) *HtmxResponse

PushURL pushes a new URL onto the browser's history stack.

func (*HtmxResponse) Redirect

func (h *HtmxResponse) Redirect(url string) *HtmxResponse

Redirect tells HTMX to perform a client-side redirect.

func (*HtmxResponse) Refresh

func (h *HtmxResponse) Refresh() *HtmxResponse

Refresh tells HTMX to do a full page refresh.

func (*HtmxResponse) ReplaceURL

func (h *HtmxResponse) ReplaceURL(url string) *HtmxResponse

ReplaceURL replaces the current URL in the browser's history.

func (*HtmxResponse) Reselect

func (h *HtmxResponse) Reselect(selector string) *HtmxResponse

Reselect changes the selection from the response.

func (*HtmxResponse) Reswap

func (h *HtmxResponse) Reswap(style string) *HtmxResponse

Reswap changes the swap method.

func (*HtmxResponse) Retarget

func (h *HtmxResponse) Retarget(selector string) *HtmxResponse

Retarget changes the target element for the swap.

func (*HtmxResponse) StopPolling

func (h *HtmxResponse) StopPolling() *HtmxResponse

StopPolling tells HTMX to stop polling.

func (*HtmxResponse) Trigger

func (h *HtmxResponse) Trigger(event string) *HtmxResponse

Trigger sets the HX-Trigger header to trigger a client-side event.

func (*HtmxResponse) TriggerAfterSettle

func (h *HtmxResponse) TriggerAfterSettle(event string) *HtmxResponse

TriggerAfterSettle sets HX-Trigger-After-Settle header.

func (*HtmxResponse) TriggerAfterSwap

func (h *HtmxResponse) TriggerAfterSwap(event string) *HtmxResponse

TriggerAfterSwap sets HX-Trigger-After-Swap header.

func (*HtmxResponse) TriggerWithData

func (h *HtmxResponse) TriggerWithData(event string, data any) *HtmxResponse

TriggerWithData sets HX-Trigger with JSON data.

type Loader

type Loader interface {
	Load(r *http.Request, w http.ResponseWriter, app any) (err error, finished bool)
}

Loader is one step of a page's Load, run in order by LoadAll. goapplib's mixins (BasePage, WithPagination, WithFiltering, WithAuth, WithHtmx) are Loaders as they are, so a page chains them with LoadAll. app is the page's *App[AC], passed through as is; a loader that needs it typed is a LoaderFunc[AC].

Before 0.7.0 this was Loader[AC], with app typed as *App[AC], which no built-in mixin satisfied (issue 107).

type LoaderFunc

type LoaderFunc[AC any] func(r *http.Request, w http.ResponseWriter, app *App[AC]) (error, bool)

LoaderFunc is a typed Loader: an app's own loading step, which gets app as its *App[AC]. Given an app of any other type, it doesn't run, and returns an error naming both types, which LoadAll returns, so a page renders a 500 rather than panicking.

func AuthLoader

func AuthLoader[AC any](auth *WithAuth, provider AuthProvider) LoaderFunc[AC]

AuthLoader returns a LoaderFunc that loads auth info, for LoadAll when you have an AuthProvider. Its app type can't be inferred, so name it: AuthLoader[*Site](&p.WithAuth, provider).

func (LoaderFunc[AC]) Load

func (f LoaderFunc[AC]) Load(r *http.Request, w http.ResponseWriter, app any) (error, bool)

Load implements Loader.

type LoginConfig

type LoginConfig struct {
	EnableEmailLogin     bool
	EnableGoogleLogin    bool
	EnableGitHubLogin    bool
	EnableMicrosoftLogin bool
	EnableAppleLogin     bool
}

LoginConfig controls which login methods are available.

type MuxBuilder

type MuxBuilder[AC any] struct {
	// contains filtered or unexported fields
}

MuxBuilder builds a ServeMux fluently, as an alternative to calling Register and RegisterGroup:

mux := app.NewMux().
	Page("/{$}", func() goapplib.View[*Site] { return &HomePage{} }).
	Group("/games", func(m *goapplib.MuxBuilder[*Site]) {
		m.Page("/{id}", func() goapplib.View[*Site] { return &GamePage{} })
	}).
	Build()

A Page renders exactly as Register would render the same view type.

func (*MuxBuilder[AC]) Build

func (b *MuxBuilder[AC]) Build() *http.ServeMux

Build returns the constructed ServeMux.

func (*MuxBuilder[AC]) Group

func (b *MuxBuilder[AC]) Group(prefix string, setup func(*MuxBuilder[AC])) *MuxBuilder[AC]

Group mounts the routes setup adds under prefix, which is stripped before they match, so a route "/{id}" in a Group("/games", ...) answers /games/7. Middleware added by Use before the Group wraps the whole group.

func (*MuxBuilder[AC]) HandleFunc

func (b *MuxBuilder[AC]) HandleFunc(pattern string, h http.HandlerFunc) *MuxBuilder[AC]

HandleFunc registers an http.HandlerFunc.

func (*MuxBuilder[AC]) Handler

func (b *MuxBuilder[AC]) Handler(pattern string, h http.Handler) *MuxBuilder[AC]

Handler registers an http.Handler.

func (*MuxBuilder[AC]) Mux

func (b *MuxBuilder[AC]) Mux() *http.ServeMux

Mux returns the underlying ServeMux for direct access.

func (*MuxBuilder[AC]) Page

func (b *MuxBuilder[AC]) Page(pattern string, maker func() View[AC], opts ...Option) *MuxBuilder[AC]

Page registers a view at pattern. maker returns a fresh view for each request, and the view's type picks its template the way Register's does (HomePage renders HomePage.html's HomePage block), unless WithTemplate says otherwise.

func (*MuxBuilder[AC]) Static

func (b *MuxBuilder[AC]) Static(pattern string, dir string) *MuxBuilder[AC]

Static serves the files in dir at pattern, with pattern stripped from the path.

func (*MuxBuilder[AC]) Use

func (b *MuxBuilder[AC]) Use(mw func(http.Handler) http.Handler) *MuxBuilder[AC]

Use adds middleware to every route registered after it on this builder, groups included. Routes registered before it aren't wrapped. Middleware added by several Uses runs in the order added.

type Option

type Option func(*options)

Option configures registration behavior.

func WithFragmentTemplate added in v0.7.2

func WithFragmentTemplate(spec string) Option

WithFragmentTemplate sets the template a page renders for an htmx request that wants a fragment rather than the whole page: when the view is HtmxAware (embedding WithHtmx makes it so, once WithHtmx has loaded) and its ShouldRenderFragment is true, which it is for an htmx request that isn't a boosted link. Any other request, or a view that isn't HtmxAware, gets the page's usual template. spec has WithTemplate's form, "path/File" or "path/File:Block".

func WithMiddleware

func WithMiddleware(mw ...func(http.Handler) http.Handler) Option

WithMiddleware adds middleware to the handler.

func WithTemplate

func WithTemplate(spec string) Option

WithTemplate sets the template file and optional block name. Format: "path/to/template" or "path/to/template:BlockName"

If no ":" is present, block name is auto-derived from the base filename. If ":" is present, the part after ":" is used as the explicit block name. An empty block name after ":" means render the entire template file.

Examples:

  • "CanvasListingPage" -> file: CanvasListingPage.html, block: CanvasListingPage (auto-derived)
  • "canvases/CanvasListingPage" -> file: canvases/CanvasListingPage.html, block: CanvasListingPage (auto-derived)
  • "canvases/CanvasListingPage:MyBlock" -> file: canvases/CanvasListingPage.html, block: MyBlock
  • "canvases/CanvasListingPage:" -> file: canvases/CanvasListingPage.html, block: "" (entire file)

type PageGroup

type PageGroup[AC any] interface {
	// RegisterRoutes returns a ServeMux with all routes for this group.
	// Patterns should be relative (prefix is stripped by RegisterGroup).
	RegisterRoutes(app *App[AC]) *http.ServeMux
}

PageGroup is the interface for a group of related pages. Implement this to define a set of routes under a common prefix.

type RateLimitConfig

type RateLimitConfig struct {
	// Auth endpoints (login, signup, forgot-password) - stricter limits
	AuthLimit  int
	AuthWindow time.Duration

	// API endpoints - more permissive
	APILimit  int
	APIWindow time.Duration
}

RateLimitConfig holds configuration for different rate limit tiers.

func DefaultRateLimitConfig

func DefaultRateLimitConfig() *RateLimitConfig

DefaultRateLimitConfig returns sensible defaults for rate limiting.

type RateLimitMiddleware

type RateLimitMiddleware struct {
	// contains filtered or unexported fields
}

RateLimitMiddleware creates HTTP middleware that applies rate limiting.

func NewRateLimitMiddleware

func NewRateLimitMiddleware(config *RateLimitConfig) *RateLimitMiddleware

NewRateLimitMiddleware creates rate limiting middleware with the given config.

func NewRateLimitMiddlewareWithKeyFunc

func NewRateLimitMiddlewareWithKeyFunc(config *RateLimitConfig, keyFunc func(*http.Request) string) *RateLimitMiddleware

NewRateLimitMiddlewareWithKeyFunc creates middleware with a custom key function.

func (*RateLimitMiddleware) Wrap

Wrap wraps any handler with the API rate limiter. This is a convenience method for handlers that aren't auth-specific.

func (*RateLimitMiddleware) WrapAPI

func (m *RateLimitMiddleware) WrapAPI(next http.Handler) http.Handler

WrapAPI wraps an API handler with rate limiting.

func (*RateLimitMiddleware) WrapAuth

func (m *RateLimitMiddleware) WrapAuth(next http.Handler) http.Handler

WrapAuth wraps an auth handler with rate limiting.

type RateLimiter

type RateLimiter struct {
	// contains filtered or unexported fields
}

RateLimiter provides a simple in-memory rate limiting using sliding window. For production with multiple instances, consider using Redis-based rate limiting.

func NewRateLimiter

func NewRateLimiter(limit int, window time.Duration) *RateLimiter

NewRateLimiter creates a new rate limiter with the specified limit per window.

func (*RateLimiter) Allow

func (rl *RateLimiter) Allow(key string) bool

Allow checks if a request from the given key should be allowed.

type SampleLoginPage

type SampleLoginPage[AC any] struct {
	BasePage
	CallbackURL string
	CsrfToken   string
	Config      LoginConfig
}

SampleLoginPage provides sample login page functionality. Embed this in your app-specific login page struct.

func (*SampleLoginPage[AC]) Load

func (p *SampleLoginPage[AC]) Load(r *http.Request, w http.ResponseWriter, app *App[AC]) (err error, finished bool)

Load implements View[AC] for SampleLoginPage.

type SampleProfilePage

type SampleProfilePage[AC any] struct {
	BasePage

	// User information
	UserID            string
	Nickname          string
	Email             string
	EmailVerified     bool
	Username          string
	Profile           map[string]any
	VerificationSent  bool
	VerificationError string
}

SampleProfilePage provides sample profile page functionality. Embed this in your app-specific profile page struct.

func (*SampleProfilePage[AC]) Load

func (p *SampleProfilePage[AC]) Load(r *http.Request, w http.ResponseWriter, app *App[AC]) (err error, finished bool)

Load implements View[AC] for SampleProfilePage.

type SampleRegisterPage

type SampleRegisterPage[AC any] struct {
	BasePage
	CallbackURL    string
	CsrfToken      string
	Name           string
	Email          string
	Password       string
	VerifyPassword string
	Errors         map[string]string
}

SampleRegisterPage provides sample registration page functionality. Embed this in your app-specific register page struct.

func (*SampleRegisterPage[AC]) Load

func (p *SampleRegisterPage[AC]) Load(r *http.Request, w http.ResponseWriter, app *App[AC]) (err error, finished bool)

Load implements View[AC] for SampleRegisterPage.

type SortOption

type SortOption struct {
	Value    string
	Label    string
	Selected bool
}

SortOption represents a sort dropdown option

type View

type View[AC any] interface {
	// Load prepares the view data from the request.
	// app provides access to the application context and templates.
	// Returns (error, finished):
	//   - error: non-nil if an error occurred (will be displayed)
	//   - finished: true if response was already written (redirect, etc.)
	Load(r *http.Request, w http.ResponseWriter, app *App[AC]) (err error, finished bool)
}

View is the interface that all pages/views must implement. AC is the application context type (e.g., *WeewarApp).

type WebAppServer

type WebAppServer struct {
	Address       string
	GrpcAddress   string
	AllowLocalDev bool
}

WebAppServer provides a generic HTTP server with optional CORS and logging.

func (*WebAppServer) StartWithHandler

func (s *WebAppServer) StartWithHandler(ctx context.Context, handler http.Handler, srvErr chan error, stopChan chan bool) error

StartWithHandler starts the HTTP server with the given handler.

type WithAuth

type WithAuth struct {
	LoggedInUserId string // Current user's ID
	Username       string // Current user's display name
	IsLoggedIn     bool   // True if user is authenticated
	IsOwner        bool   // True if user owns the current entity
}

WithAuth provides authentication info. Embed this in page structs that need user info.

func (*WithAuth) Load

func (p *WithAuth) Load(r *http.Request, w http.ResponseWriter, vc any) (error, bool)

Load is a no-op for WithAuth. Use LoadWithAuth to load auth info with your auth services.

func (*WithAuth) LoadWithAuth

func (p *WithAuth) LoadWithAuth(r *http.Request, provider AuthProvider) (error, bool)

LoadWithAuth loads auth info using the provided auth services.

type WithFiltering

type WithFiltering struct {
	Query    string // Search query
	Sort     string // Sort field/direction
	ViewMode string // Display mode: "grid", "table", etc.
}

WithFiltering provides search and sort support. Embed this in page structs that support filtering.

func (*WithFiltering) Load

func (p *WithFiltering) Load(r *http.Request, w http.ResponseWriter, vc any) (error, bool)

Load implements Loader for WithFiltering.

type WithHtmx

type WithHtmx struct {
	IsHtmx      bool   // True if this is an HTMX request
	IsBoosted   bool   // True if this is a boosted link
	Target      string // HX-Target header value
	Trigger     string // HX-Trigger header value
	TriggerName string // HX-Trigger-Name header value
	CurrentURL  string // HX-Current-URL header value
	Prompt      string // HX-Prompt header value
}

WithHtmx provides HTMX request detection. Embed this in page structs that need HTMX-aware rendering.

func (*WithHtmx) Load

func (p *WithHtmx) Load(r *http.Request, w http.ResponseWriter, vc any) (error, bool)

Load implements Loader for WithHtmx.

func (*WithHtmx) ShouldRenderFragment

func (p *WithHtmx) ShouldRenderFragment() bool

ShouldRenderFragment returns true if only a fragment should be rendered.

type WithPagination

type WithPagination struct {
	CurrentPage int   // 0-indexed current page
	PageSize    int   // Items per page
	TotalCount  int   // Total number of items
	HasPrevPage bool  // True if there's a previous page
	HasNextPage bool  // True if there's a next page
	Pages       []int // Page numbers to display in pagination UI
}

WithPagination provides pagination support. Embed this in page structs that display paginated lists.

func (*WithPagination) EvalPages

func (p *WithPagination) EvalPages()

EvalPages calculates page numbers to display.

func (*WithPagination) Load

func (p *WithPagination) Load(r *http.Request, w http.ResponseWriter, vc any) (error, bool)

Load implements Loader for WithPagination.

func (*WithPagination) NextPage

func (p *WithPagination) NextPage() int

NextPage returns the next page number.

func (*WithPagination) Offset

func (p *WithPagination) Offset() int

Offset returns the offset for database queries.

func (*WithPagination) Paginator

func (p *WithPagination) Paginator() *WithPagination

Paginator returns self for template access via .Paginator This allows templates to use {{ .Paginator.HasPrevPage }} etc. when the page struct embeds WithPagination.

func (*WithPagination) PrevPage

func (p *WithPagination) PrevPage() int

PrevPage returns the previous page number.

func (*WithPagination) SetTotal

func (p *WithPagination) SetTotal(total int, hasMore bool)

SetTotal updates pagination state based on total count.

func (*WithPagination) TotalPages added in v0.7.2

func (p *WithPagination) TotalPages() int

TotalPages is how many pages TotalCount fills at PageSize, or 0 before SetTotal. goapplib's Pagination template shows it.

Directories

Path Synopsis
content
gen/datastore/collections/v1
Code generated by protoc-gen-dal-datastore.
Code generated by protoc-gen-dal-datastore.
gen/datastore/dal/collections/v1
Code generated by protoc-gen-dal-datastore.
Code generated by protoc-gen-dal-datastore.
gen/datastore/dal/likes/v1
Code generated by protoc-gen-dal-datastore.
Code generated by protoc-gen-dal-datastore.
gen/datastore/dal/tags/v1
Code generated by protoc-gen-dal-datastore.
Code generated by protoc-gen-dal-datastore.
gen/datastore/likes/v1
Code generated by protoc-gen-dal-datastore.
Code generated by protoc-gen-dal-datastore.
gen/datastore/tags/v1
Code generated by protoc-gen-dal-datastore.
Code generated by protoc-gen-dal-datastore.
gen/go/collections/v1
Package collectionsv1 is a reverse proxy.
Package collectionsv1 is a reverse proxy.
gen/go/likes/v1
Package likesv1 is a reverse proxy.
Package likesv1 is a reverse proxy.
gen/go/tags/v1
Package tagsv1 is a reverse proxy.
Package tagsv1 is a reverse proxy.
gen/gorm/collections/v1
Code generated by protoc-gen-dal-gorm.
Code generated by protoc-gen-dal-gorm.
gen/gorm/dal/collections/v1
Code generated by protoc-gen-dal-gorm.
Code generated by protoc-gen-dal-gorm.
gen/gorm/dal/likes/v1
Code generated by protoc-gen-dal-gorm.
Code generated by protoc-gen-dal-gorm.
gen/gorm/dal/tags/v1
Code generated by protoc-gen-dal-gorm.
Code generated by protoc-gen-dal-gorm.
gen/gorm/likes/v1
Code generated by protoc-gen-dal-gorm.
Code generated by protoc-gen-dal-gorm.
gen/gorm/tags/v1
Code generated by protoc-gen-dal-gorm.
Code generated by protoc-gen-dal-gorm.
services/collections
Package collections provides Connect RPC adapters for the CollectionsService.
Package collections provides Connect RPC adapters for the CollectionsService.
services/collections/backends
Package backends provides concrete storage implementations for the collections service.
Package backends provides concrete storage implementations for the collections service.
services/common
Package common provides shared utilities for content services.
Package common provides shared utilities for content services.
services/likes
Package likes provides Connect RPC adapters for the LikesService.
Package likes provides Connect RPC adapters for the LikesService.
services/likes/backends
Package backends provides concrete storage implementations for the likes service.
Package backends provides concrete storage implementations for the likes service.
services/tags
Package tags provides Connect RPC adapters for the TagsService.
Package tags provides Connect RPC adapters for the TagsService.
services/tags/backends
Package backends provides concrete storage implementations for the tags service.
Package backends provides concrete storage implementations for the tags service.
Package datastore provides shared utilities for Google Cloud Datastore backends.
Package datastore provides shared utilities for Google Cloud Datastore backends.
exercise
islands command
The exercise for mission #60 (goapplib issue 61): a server-rendered page whose spec names three islands with different load strategies, drawn by goapplib's own PageSpecScript partial.
The exercise for mission #60 (goapplib issue 61): a server-rendered page whose spec names three islands with different load strategies, drawn by goapplib's own PageSpecScript partial.
wasmhost/gen/go/files/v1/filesv1connect
A toy service for the wasmhost exercise (goapplib issue 33).
A toy service for the wasmhost exercise (goapplib issue 33).
wasmhost/service
Package service is the exercise's toy FilesService.
Package service is the exercise's toy FilesService.
wasmhost/wasm command
The exercise's wasm build: FilesService served from a Web Worker on globalThis.files.
The exercise's wasm build: FilesService served from a Web Worker on globalThis.files.
workerstate/service
Package service is the toy stateful service behind mission #74's exercise (goapplib issue 75).
Package service is the toy stateful service behind mission #74's exercise (goapplib issue 75).
workerstate/wasm command
The worker side of the worker-state exercise: the toy service as wasm, behind wasmhost.
The worker side of the worker-state exercise: the toy service as wasm, behind wasmhost.
gen
datastore
Code generated by protoc-gen-dal-datastore.
Code generated by protoc-gen-dal-datastore.
datastore/dal
Code generated by protoc-gen-dal-datastore.
Code generated by protoc-gen-dal-datastore.
go/goapplib/v1
Package goapplibv1 is a reverse proxy.
Package goapplibv1 is a reverse proxy.
gorm
Code generated by protoc-gen-dal-gorm.
Code generated by protoc-gen-dal-gorm.
gorm/dal
Code generated by protoc-gen-dal-gorm.
Code generated by protoc-gen-dal-gorm.
Package page describes which islands a page mounts and where, as a Spec the server writes into the page for the browser to read (tsappkit's island page mounts each island from a registry by name).
Package page describes which islands a page mounts and where, as a Spec the server writes into the page for the browser to read (tsappkit's island page mounts each island from a registry by name).
Package services provides reusable service implementations for user management and authentication.
Package services provides reusable service implementations for user management and authentication.
backends/fs
Package fs provides a filesystem-based implementation of the UsersService.
Package fs provides a filesystem-based implementation of the UsersService.
backends/gae
Package gae provides a Google Cloud Datastore session store for scs (alexedwards/scs/v2).
Package gae provides a Google Cloud Datastore session store for scs (alexedwards/scs/v2).
backends/gorm
Package gorm provides a GORM-based implementation of the UsersService.
Package gorm provides a GORM-based implementation of the UsersService.
Package wasmhost runs an app's HTTP services (typically Connect handlers) as WebAssembly inside a browser Web Worker, answering the same generated clients a server answers.
Package wasmhost runs an app's HTTP services (typically Connect handlers) as WebAssembly inside a browser Web Worker, answering the same generated clients a server answers.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL