Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions content/contributing/livetemplate.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
title: "Contributing to LiveTemplate Core Library"
source_repo: "https://github.com/livetemplate/livetemplate"
source_path: "CONTRIBUTING.md"
source_ref: "v0.11.1"
source_commit: "37dae7f35e960ff7647a0f1eb51d89bcc62d173a"
source_ref: "v0.12.0"
source_commit: "6e9ead8f8e03f16170c2e41d407e24a646c96c22"
---

# Contributing to LiveTemplate Core Library
Expand All @@ -17,7 +17,7 @@ LiveTemplate is distributed across multiple repositories. Please use the appropr
- **[Core Library](https://github.com/livetemplate/livetemplate)** (this repo) - Go server-side library
- **[Client Library](https://github.com/livetemplate/client)** - TypeScript client for browsers → [Client CONTRIBUTING.md](/contributing/client)
- **[CLI Tool (lvt)](https://github.com/livetemplate/lvt)** - Code generator and dev server → [LVT CONTRIBUTING.md](/contributing/cli)
- **[Examples](https://github.com/livetemplate/examples)** - Example applications → [Examples CONTRIBUTING.md](/contributing/examples)
- **[Examples](https://github.com/livetemplate/examples)** - Example applications → [Examples CONTRIBUTING.md](https://github.com/livetemplate/examples/blob/main/CONTRIBUTING.md)

---

Expand Down
4 changes: 2 additions & 2 deletions content/guides/ephemeral-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
title: "Ephemeral Components Guide"
source_repo: "https://github.com/livetemplate/livetemplate"
source_path: "docs/guides/ephemeral-components.md"
source_ref: "v0.11.1"
source_commit: "37dae7f35e960ff7647a0f1eb51d89bcc62d173a"
source_ref: "v0.12.0"
source_commit: "6e9ead8f8e03f16170c2e41d407e24a646c96c22"
---

# Ephemeral Components Guide
Expand Down
4 changes: 2 additions & 2 deletions content/guides/observability.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
title: "LiveTemplate Observability Guide"
source_repo: "https://github.com/livetemplate/livetemplate"
source_path: "docs/guides/OBSERVABILITY.md"
source_ref: "v0.11.1"
source_commit: "37dae7f35e960ff7647a0f1eb51d89bcc62d173a"
source_ref: "v0.12.0"
source_commit: "6e9ead8f8e03f16170c2e41d407e24a646c96c22"
---

# LiveTemplate Observability Guide
Expand Down
4 changes: 2 additions & 2 deletions content/guides/progressive-complexity.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
title: "Progressive Complexity Guide"
source_repo: "https://github.com/livetemplate/livetemplate"
source_path: "docs/guides/progressive-complexity.md"
source_ref: "v0.11.1"
source_commit: "37dae7f35e960ff7647a0f1eb51d89bcc62d173a"
source_ref: "v0.12.0"
source_commit: "6e9ead8f8e03f16170c2e41d407e24a646c96c22"
---

# Progressive Complexity Guide
Expand Down
16 changes: 2 additions & 14 deletions content/guides/scaling.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
---
title: "LiveTemplate Scaling Guide"
description: "How to scale LiveTemplate apps from one process to Redis-backed multi-instance production deployments."
source_repo: "https://github.com/livetemplate/livetemplate"
source_path: "docs/guides/SCALING.md"
source_ref: "v0.11.1"
source_commit: "37dae7f35e960ff7647a0f1eb51d89bcc62d173a"
source_ref: "v0.12.0"
source_commit: "6e9ead8f8e03f16170c2e41d407e24a646c96c22"
---

# LiveTemplate Scaling Guide
Expand All @@ -13,17 +12,6 @@ source_commit: "37dae7f35e960ff7647a0f1eb51d89bcc62d173a"

**Last Updated:** 2025-11-01

## At a glance

| Situation | Default choice | See |
|---|---|---|
| Prototype or small internal tool | Single instance with memory session store | [Tier 1: Single Host](#tier-1-single-host-hobby) |
| Small production app | Add Redis for persistence and safer restarts | [Tier 2: Small Production](#tier-2-small-production-startup) |
| Multiple app instances | Redis session store plus pub/sub | [Migration Guide: Memory to Redis Session Store](#migration-guide-memory-to-redis-session-store) |
| Kubernetes or orchestrated deploy | Use tier checklists before scaling up | [Scaling Checklist](#scaling-checklist) |
| Capacity planning | Estimate WebSocket memory and Redis memory separately | [Capacity Planning](#capacity-planning) |
| Production rollout | Monitor connection counts, publish latency, and error rates | [Monitoring and Alerting](#monitoring-and-alerting) |

---

## Overview
Expand Down
29 changes: 20 additions & 9 deletions content/guides/standard-html-reactivity.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
title: "Standard HTML Reactivity"
source_repo: "https://github.com/livetemplate/livetemplate"
source_path: "docs/guides/standard-html-reactivity.md"
source_ref: "v0.11.1"
source_commit: "37dae7f35e960ff7647a0f1eb51d89bcc62d173a"
source_ref: "v0.12.0"
source_commit: "6e9ead8f8e03f16170c2e41d407e24a646c96c22"
---

# Standard HTML Reactivity
Expand Down Expand Up @@ -103,19 +103,30 @@ See [PubSub Reference](../references/pubsub.md) for details.

## Comparison with Other Frameworks

Every major reactive framework requires custom attributes on HTML elements. LiveTemplate is unique in making standard HTML reactive without modification.
Every major reactive framework makes HTML reactive by adding a layer on top of it — custom attributes (`hx-*`, `wire:*`, `phx-*`) or a templating DSL.

| Framework | Form markup required | Custom attributes |
|-----------|---------------------|-------------------|
| **htmx** | `<form hx-post="/todos" hx-target="#list">` | `hx-post`, `hx-target`, `hx-swap`, `hx-trigger` |
| **Laravel Livewire** | `<form wire:submit="add">` | `wire:submit`, `wire:model`, `wire:click` |
| **Phoenix LiveView** | `<form phx-submit="add">` | `phx-submit`, `phx-click`, `phx-change` |
| **LiveTemplate** | `<form method="POST">` | None for standard interactions |
LiveTemplate keeps the HTML standard and moves the reactivity to the server. You add an `lvt-*` attribute only when the behavior is something HTML itself cannot define — timing, keyboard shortcuts, reactive DOM — never to make ordinary HTML reactive.

The boundary is *what HTML can express*, not *how common the case is*.

| Framework | Markup for a form action | Attributes to make it reactive |
|-----------|--------------------------|--------------------------------|
| **htmx** | `<form hx-post="/todos">` | `hx-post`, `hx-target`, `hx-swap`, `hx-trigger` |
| **templ + htmx** | `<form hx-post="/todos">` (authored in templ, a Go DSL) | `hx-post`, `hx-target`, `hx-swap`, `hx-trigger` |
| **Laravel Livewire** | `<form wire:submit="add">` (Blade) | `wire:submit`, `wire:model`, `wire:click` |
| **Phoenix LiveView** | `<form phx-submit="add">` (HEEx) | `phx-submit`, `phx-click`, `phx-change` |
| **LiveTemplate** | `<form method="POST">` (standard `html/template`) | None for standard interactions; `lvt-*` only for what HTML can't express |

### htmx

htmx extends HTML with `hx-*` attributes for AJAX interactions. A form without `hx-post` submits normally (full page reload). Every interactive element needs explicit `hx-*` attributes.

### templ + htmx

[templ](https://templ.guide) is a Go DSL for authoring and composing HTML as type-safe Go components — a popular alternative to `html/template`. It is a *templating* layer, not an interactivity layer, so it is commonly paired with htmx for reactivity. That means two things to learn and adopt: a new markup language **and** `hx-*` attributes on the rendered HTML.

LiveTemplate takes the opposite trade: it stays on Go's standard `html/template` (no new DSL) and provides the reactivity itself. You compose with what `html/template` already gives you — partials and the `{{template}}` action — plus per-session state and one render-and-diff pipeline, rather than adopting a new language for either authoring or interactivity. If you specifically want compile-time-checked, function-composed markup, templ is the better fit; if you want standard HTML to be reactive without a DSL or `hx-*` wiring, that's LiveTemplate.

### Laravel Livewire

Livewire uses `wire:*` directives in PHP/Blade templates. `wire:submit` captures form submissions, `wire:model` enables two-way binding. State is serialized into HTML attributes.
Expand Down
16 changes: 2 additions & 14 deletions content/reference/api.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,15 @@
---
title: "Go Library API Reference"
description: "Reference for the LiveTemplate Go API: templates, controllers, state, context, sessions, auth, stores, uploads, and pub/sub."
source_repo: "https://github.com/livetemplate/livetemplate"
source_path: "docs/references/api-reference.md"
source_ref: "v0.11.1"
source_commit: "37dae7f35e960ff7647a0f1eb51d89bcc62d173a"
source_ref: "v0.12.0"
source_commit: "6e9ead8f8e03f16170c2e41d407e24a646c96c22"
---

# Go Library API Reference

> **Scope:** This reference documents the **`livetemplate` Go library** (`github.com/livetemplate/livetemplate`). For the CLI tool, see the [lvt repository](https://github.com/livetemplate/lvt).

## At a glance

| Need | Start with | See |
|---|---|---|
| Parse and mount a template | `New`, `ParseFiles`, `Handle` | [Template](#template) |
| Keep dependencies separate from UI state | Controller singleton + `AsState` | [Controller+State Pattern](#controllerstate-pattern) |
| Read submitted form data | `ctx.GetString`, `ctx.Bind`, `ctx.BindAndValidate` | [Data Extraction](#data-extraction) |
| Persist lightweight session fields | `lvt:"persist"` on state fields | [Session](#session) |
| Push work to connected clients | `Session.TriggerAction` or `ctx.Publish` | [Session](#session), [PubSub](#pubsub-cross-instance-peer-fan-out) |
| Configure auth, stores, uploads, and limits | `Option` and `HandleOption` values | [Configuration](#configuration) |

## Quick Start

```go
Expand Down
43 changes: 36 additions & 7 deletions content/reference/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
title: "Authentication Reference"
source_repo: "https://github.com/livetemplate/livetemplate"
source_path: "docs/references/authentication.md"
source_ref: "v0.11.1"
source_commit: "37dae7f35e960ff7647a0f1eb51d89bcc62d173a"
source_ref: "v0.12.0"
source_commit: "6e9ead8f8e03f16170c2e41d407e24a646c96c22"
---

# Authentication Reference
Expand Down Expand Up @@ -201,16 +201,45 @@ ctx.DeleteCookie("session_token") // Sets MaxAge = -1
ctx.Redirect("/dashboard", http.StatusSeeOther) // 303
```

**Security:** Only relative paths starting with `/` are allowed. This prevents open redirect vulnerabilities:
The target may be an **absolute-path reference** (`/dashboard`) or a **relative
reference** (`""`, `.`, `./settings`, `../list`). Relative references are
emitted as-is in the `Location` header, so the browser resolves them against
its own request URL.

**Redirecting to your own mount (recipes behind `http.StripPrefix`):** When a
handler is mounted at a subpath via `http.StripPrefix("/apps/login/", handler)`,
`r.URL.Path` is stripped before the handler sees it, so the handler can't
reconstruct its own mount. Use the empty string — "reload self" — and let the
browser resolve it against the full URL:

```go
// POST-Redirect-GET back to the recipe's own mount, wherever it's mounted.
return state, ctx.Redirect("", http.StatusSeeOther)
```

This lands back at `/apps/login/` in production and at `/` under a root-mounted
test server — no `mountPath` argument needs threading through the handler.

> **Mount with a trailing slash.** The empty-string "reload self" form resolves
> to `./` (the current directory), so it relies on the canonical trailing-slash
> mount `http.StripPrefix("/apps/login/", …)`. An exact-match mount *without* a
> trailing slash (`http.StripPrefix("/apps/login", …)` serving `/apps/login`)
> would resolve `./` to the parent path.

**Security:** Relative references are origin-confined (RFC 3986 resolution
keeps the current scheme+host), so they can't be open-redirect vectors. The
guard rejects anything that could escape the current origin:

```go
// Valid redirects
ctx.Redirect("/dashboard", http.StatusSeeOther) // OK
ctx.Redirect("/users/profile", http.StatusFound) // OK
ctx.Redirect("/dashboard", http.StatusSeeOther) // OK (absolute path)
ctx.Redirect("", http.StatusSeeOther) // OK (reload self)
ctx.Redirect("./settings", http.StatusSeeOther) // OK (relative)

// Invalid redirects (rejected with ErrInvalidRedirectURL)
ctx.Redirect("https://evil.com", http.StatusFound) // Rejected
ctx.Redirect("https://evil.com", http.StatusFound) // Rejected (has scheme/host)
ctx.Redirect("//evil.com", http.StatusFound) // Rejected (protocol-relative)
ctx.Redirect("/\\evil.com", http.StatusFound) // Rejected (backslash bypass)
```

### Error Types
Expand All @@ -224,7 +253,7 @@ var (
ErrInvalidRedirectCode = errors.New("invalid redirect status code (must be 3xx)")

// Returned when Redirect URL could cause open redirect vulnerability
ErrInvalidRedirectURL = errors.New("invalid redirect URL (must be relative path starting with /)")
ErrInvalidRedirectURL = errors.New("invalid redirect URL (must be a path or relative reference with no scheme or host)")
)
```

Expand Down
4 changes: 2 additions & 2 deletions content/reference/client-attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
title: "Client Attributes Reference"
source_repo: "https://github.com/livetemplate/livetemplate"
source_path: "docs/references/client-attributes.md"
source_ref: "v0.11.1"
source_commit: "37dae7f35e960ff7647a0f1eb51d89bcc62d173a"
source_ref: "v0.12.0"
source_commit: "6e9ead8f8e03f16170c2e41d407e24a646c96c22"
---

# Client Attributes Reference
Expand Down
4 changes: 2 additions & 2 deletions content/reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
title: "LiveTemplate Configuration Guide"
source_repo: "https://github.com/livetemplate/livetemplate"
source_path: "docs/references/CONFIGURATION.md"
source_ref: "v0.11.1"
source_commit: "37dae7f35e960ff7647a0f1eb51d89bcc62d173a"
source_ref: "v0.12.0"
source_commit: "6e9ead8f8e03f16170c2e41d407e24a646c96c22"
---

# LiveTemplate Configuration Guide
Expand Down
4 changes: 2 additions & 2 deletions content/reference/controller-pattern.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
title: "Controller+State Pattern Reference"
source_repo: "https://github.com/livetemplate/livetemplate"
source_path: "docs/references/controller-pattern.md"
source_ref: "v0.11.1"
source_commit: "37dae7f35e960ff7647a0f1eb51d89bcc62d173a"
source_ref: "v0.12.0"
source_commit: "6e9ead8f8e03f16170c2e41d407e24a646c96c22"
---

# Controller+State Pattern Reference
Expand Down
15 changes: 2 additions & 13 deletions content/reference/error-handling.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,15 @@
---
title: "Error Handling Reference"
description: "How LiveTemplate propagates server errors, validation failures, form lifecycle events, template error state, and flash messages."
source_repo: "https://github.com/livetemplate/livetemplate"
source_path: "docs/references/error-handling.md"
source_ref: "v0.11.1"
source_commit: "37dae7f35e960ff7647a0f1eb51d89bcc62d173a"
source_ref: "v0.12.0"
source_commit: "6e9ead8f8e03f16170c2e41d407e24a646c96c22"
---

# Error Handling Reference

Complete guide to error handling in LiveTemplate applications.

## At a glance

| Need | Use | See |
|---|---|---|
| Stop an action and keep state unchanged | Return an error from the controller method | [Server-Side Errors](#server-side-errors) |
| Show field-level validation messages | `FieldError`, `MultiError`, or validator integration | [Validation Errors](#validation-errors) |
| Render errors in templates | Error helpers and error-aware template state | [Template Error Display](#template-error-display) |
| React to failed submissions in the browser | `lvt:error` lifecycle hooks | [Client-Side Error Handling](#client-side-error-handling) |
| Show one-shot success or failure messages | Flash helpers on `Context` | [Flash Messages](#flash-messages) |

## Table of Contents

- [Overview](#overview)
Expand Down
4 changes: 2 additions & 2 deletions content/reference/limitations.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
title: "Current Limitations"
source_repo: "https://github.com/livetemplate/livetemplate"
source_path: "docs/references/current-limitations.md"
source_ref: "v0.11.1"
source_commit: "37dae7f35e960ff7647a0f1eb51d89bcc62d173a"
source_ref: "v0.12.0"
source_commit: "6e9ead8f8e03f16170c2e41d407e24a646c96c22"
---

# Current Limitations
Expand Down
4 changes: 2 additions & 2 deletions content/reference/navigate.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
title: "Navigate Action Reference"
source_repo: "https://github.com/livetemplate/livetemplate"
source_path: "docs/references/navigate.md"
source_ref: "v0.11.1"
source_commit: "37dae7f35e960ff7647a0f1eb51d89bcc62d173a"
source_ref: "v0.12.0"
source_commit: "6e9ead8f8e03f16170c2e41d407e24a646c96c22"
---

# Navigate Action Reference
Expand Down
4 changes: 2 additions & 2 deletions content/reference/progressive-complexity.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
title: "Progressive Complexity Reference"
source_repo: "https://github.com/livetemplate/livetemplate"
source_path: "docs/references/progressive-complexity-reference.md"
source_ref: "v0.11.1"
source_commit: "37dae7f35e960ff7647a0f1eb51d89bcc62d173a"
source_ref: "v0.12.0"
source_commit: "6e9ead8f8e03f16170c2e41d407e24a646c96c22"
---

# Progressive Complexity Reference
Expand Down
4 changes: 2 additions & 2 deletions content/reference/pubsub.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
title: "PubSub Reference"
source_repo: "https://github.com/livetemplate/livetemplate"
source_path: "docs/references/pubsub.md"
source_ref: "v0.11.1"
source_commit: "37dae7f35e960ff7647a0f1eb51d89bcc62d173a"
source_ref: "v0.12.0"
source_commit: "6e9ead8f8e03f16170c2e41d407e24a646c96c22"
---

# PubSub Reference
Expand Down
Loading
Loading