diff --git a/content/changelog/livetemplate.md b/content/changelog/livetemplate.md
index cec0d2d..45585bf 100644
--- a/content/changelog/livetemplate.md
+++ b/content/changelog/livetemplate.md
@@ -2,8 +2,8 @@
title: "Changelog"
source_repo: "https://github.com/livetemplate/livetemplate"
source_path: "CHANGELOG.md"
-source_ref: "v0.22.0"
-source_commit: "22a4853506a682583b511e470bdd1e6193f4d5fe"
+source_ref: "v0.23.0"
+source_commit: "8294ce439a46a6a1f92e2a77b8a4978c9e526cc6"
---
# Changelog
@@ -13,6 +13,35 @@ All notable changes to LiveTemplate will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [v0.23.0] - 2026-08-02
+
+### Added
+
+- **`LiveHandler.Func()` returns `ServeHTTP` as an `http.HandlerFunc`.** The
+ value `Template.Handle()` returns already satisfied `http.Handler`, so
+ `http.Handle`/`mux.Handle` worked, but the stdlib entry points that take a
+ function — `http.HandleFunc`, and `ServeMux.HandleFunc` with Go 1.22 method
+ patterns — required spelling out `handler.ServeHTTP`. `Func()` is that method
+ value, so `http.HandleFunc("/counter", handler.Func())` and
+ `mux.HandleFunc("GET /counter", handler.Func())` read naturally. It is an
+ accessor, not a downgrade: `Shutdown`, `Publish` and `MetricsHandler` stay
+ available on the `LiveHandler` it came from.
+
+### Changed
+
+- **A failed WebSocket upgrade now logs a `hint` when the `http.ResponseWriter`
+ does not implement `http.Hijacker`.** An upgrade takes over the raw
+ connection, so middleware that wraps the writer (logging, gzip, status
+ capture) without forwarding `Hijack` breaks it — while GET and POST keep
+ rendering, making the symptom "the page renders but never goes live". The
+ underlying upgrader error names `http.Hijacker` but not the middleware that
+ caused it; the hint does, and points at forwarding `Hijack` or leaving the
+ writer unwrapped when `livetemplate.WSIsUpgrade(r)` is true. It is attached on
+ the writer's own defect, which need not be what the accompanying error reports
+ — an upgrader can reject a handshake earlier (a disallowed `Origin`) and never
+ reach the hijack — so it is worded as a second failure the upgrade would have
+ hit regardless, rather than as the reported cause.
+
## [v0.22.0] - 2026-07-26
### Added
diff --git a/content/contributing/livetemplate.md b/content/contributing/livetemplate.md
index 31f4642..25fbd03 100644
--- a/content/contributing/livetemplate.md
+++ b/content/contributing/livetemplate.md
@@ -2,8 +2,8 @@
title: "Contributing to LiveTemplate Core Library"
source_repo: "https://github.com/livetemplate/livetemplate"
source_path: "CONTRIBUTING.md"
-source_ref: "v0.22.0"
-source_commit: "22a4853506a682583b511e470bdd1e6193f4d5fe"
+source_ref: "v0.23.0"
+source_commit: "8294ce439a46a6a1f92e2a77b8a4978c9e526cc6"
---
# Contributing to LiveTemplate Core Library
@@ -226,7 +226,7 @@ livetemplate/
└── scripts/ # Development scripts
```
-For the complete file-by-file map with line counts and dependencies, see [docs/design/CODE_STRUCTURE.md](https://github.com/livetemplate/livetemplate/blob/v0.22.0/docs/design/CODE_STRUCTURE.md).
+For the complete file-by-file map with line counts and dependencies, see [docs/design/CODE_STRUCTURE.md](https://github.com/livetemplate/livetemplate/blob/v0.23.0/docs/design/CODE_STRUCTURE.md).
**Note:** The client library, CLI tool, and examples are now in separate repositories:
- Client: https://github.com/livetemplate/client
@@ -528,7 +528,7 @@ Look for issues labeled `good first issue` - these are:
### Learning the Codebase
1. **Start with the Contributor Walkthrough**
- - [`docs/guides/new-contributor-walkthrough.md`](https://github.com/livetemplate/livetemplate/blob/v0.22.0/docs/guides/new-contributor-walkthrough.md) - **START HERE!** Comprehensive guide to the 5-phase architecture with links to all code and tests
+ - [`docs/guides/new-contributor-walkthrough.md`](https://github.com/livetemplate/livetemplate/blob/v0.23.0/docs/guides/new-contributor-walkthrough.md) - **START HERE!** Comprehensive guide to the 5-phase architecture with links to all code and tests
2. **Read the architecture docs**
- `CLAUDE.md` - Development guidelines
diff --git a/content/guides/ephemeral-components.md b/content/guides/ephemeral-components.md
index ce34da4..c56578c 100644
--- a/content/guides/ephemeral-components.md
+++ b/content/guides/ephemeral-components.md
@@ -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.22.0"
-source_commit: "22a4853506a682583b511e470bdd1e6193f4d5fe"
+source_ref: "v0.23.0"
+source_commit: "8294ce439a46a6a1f92e2a77b8a4978c9e526cc6"
---
# Ephemeral Components Guide
@@ -62,7 +62,7 @@ type AppState struct {
}
```
-> **Note on `AssertPureState`**: If your tests use `lvt/testing.AssertPureState[T](https://github.com/livetemplate/livetemplate/blob/v0.22.0/docs/guides/t)` to verify state contains no dependency types, `*toast.Container` will need to be excluded. Component containers are not external dependencies — they hold transient UI data, not connections or handles. Use `AssertPureState` with the `IgnoreFields` option, or structure your state so component fields live in a separate struct that is not checked.
+> **Note on `AssertPureState`**: If your tests use `lvt/testing.AssertPureState[T](https://github.com/livetemplate/livetemplate/blob/v0.23.0/docs/guides/t)` to verify state contains no dependency types, `*toast.Container` will need to be excluded. Component containers are not external dependencies — they hold transient UI data, not connections or handles. Use `AssertPureState` with the `IgnoreFields` option, or structure your state so component fields live in a separate struct that is not checked.
### Initialization
diff --git a/content/guides/observability.md b/content/guides/observability.md
index 7dbec02..b90d2d8 100644
--- a/content/guides/observability.md
+++ b/content/guides/observability.md
@@ -2,8 +2,8 @@
title: "LiveTemplate Observability Guide"
source_repo: "https://github.com/livetemplate/livetemplate"
source_path: "docs/guides/OBSERVABILITY.md"
-source_ref: "v0.22.0"
-source_commit: "22a4853506a682583b511e470bdd1e6193f4d5fe"
+source_ref: "v0.23.0"
+source_commit: "8294ce439a46a6a1f92e2a77b8a4978c9e526cc6"
---
# LiveTemplate Observability Guide
@@ -409,6 +409,6 @@ func RequestIDMiddleware(next http.Handler) http.Handler {
## Related Documentation
-- [ARCHITECTURE.md](https://github.com/livetemplate/livetemplate/blob/v0.22.0/docs/guides/ARCHITECTURE.md) - System architecture overview
-- [internal/observe/](https://github.com/livetemplate/livetemplate/tree/v0.22.0/docs/internal/observe) - Package implementation
+- [ARCHITECTURE.md](https://github.com/livetemplate/livetemplate/blob/v0.23.0/docs/design/ARCHITECTURE.md) - System architecture overview
+- [internal/observe/](https://github.com/livetemplate/livetemplate/tree/v0.23.0/internal/observe) - Package implementation
- [Go slog documentation](https://pkg.go.dev/log/slog) - Standard library reference
diff --git a/content/guides/progressive-complexity.md b/content/guides/progressive-complexity.md
index 5002f7d..3464f96 100644
--- a/content/guides/progressive-complexity.md
+++ b/content/guides/progressive-complexity.md
@@ -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.22.0"
-source_commit: "22a4853506a682583b511e470bdd1e6193f4d5fe"
+source_ref: "v0.23.0"
+source_commit: "8294ce439a46a6a1f92e2a77b8a4978c9e526cc6"
---
# Progressive Complexity Guide
@@ -236,10 +236,11 @@ LiveTemplate offers three loading models. Pick the simplest one that fits your u
|---|---|---|---|
| Grey out the form | N/A | **7.1 — Auto** (`