diff --git a/go.mod b/go.mod
index 851cafb..c70bbe1 100644
--- a/go.mod
+++ b/go.mod
@@ -3,6 +3,7 @@ module examples
 go 1.21
 
 require (
+	github.com/a-h/pathvars v0.0.12
 	github.com/a-h/templ v0.2.234-0.20230416205859-20293271f3c5
 	github.com/rs/xid v1.5.0
 	github.com/yosssi/gohtml v0.0.0-20201013000340-ee4748c638f4
diff --git a/go.sum b/go.sum
index cad4968..fb3442e 100644
--- a/go.sum
+++ b/go.sum
@@ -1,3 +1,5 @@
+github.com/a-h/pathvars v0.0.12 h1:B4JaZGvHKNgNNlw8LMayPM/Hc0f3xZ2PXivu8YIl/X0=
+github.com/a-h/pathvars v0.0.12/go.mod h1:7rLTtvDVyKneR/N65hC0lh2sZ2KRyAmWFaOvv00uxb0=
 github.com/a-h/templ v0.2.233 h1:EnZqZmtV0YICqWG6MtLNmTcWuFkl2ImyQ63SIpWaM2Y=
 github.com/a-h/templ v0.2.233/go.mod h1:h1DdzFMWVApvTcZBNmM6+mD6EPq6uYkncMNF7zdLj9I=
 github.com/a-h/templ v0.2.234-0.20230416205859-20293271f3c5 h1:NeF/iw7KU9W7CYYJimd5x7ooOXCLrfo8FcHdFPUU+2w=
diff --git a/inlinevalidation/handlers.go b/inlinevalidation/handlers.go
new file mode 100644
index 0000000..ad6b88e
--- /dev/null
+++ b/inlinevalidation/handlers.go
@@ -0,0 +1,78 @@
+package inlinevalidation
+
+import (
+	"errors"
+	"net/http"
+
+	"github.com/a-h/pathvars"
+)
+
+var validateMatcher = pathvars.NewExtractor("/inline-validation/validate/{name}")
+
+func Handlers(prefix string, mux *http.ServeMux) {
+	mux.HandleFunc(prefix+"/", index)
+	mux.HandleFunc(prefix+"/validate/", validate)
+}
+
+func index(w http.ResponseWriter, r *http.Request) {
+	Index().Render(r.Context(), w)
+}
+
+func validate(w http.ResponseWriter, r *http.Request) {
+	vals, ok := validateMatcher.Extract(r.URL)
+	if !ok {
+		w.WriteHeader(500)
+		return
+	}
+	name, ok := vals["name"]
+	if !ok {
+		w.WriteHeader(500)
+		return
+	}
+	f, ok := fields[name]
+	if !ok {
+		w.WriteHeader(500)
+		return
+	}
+	if err := r.ParseForm(); err != nil {
+		w.WriteHeader(500)
+		return
+	}
+	val := r.FormValue(name)
+	inp(f, name, val, f.validator(val)).Render(r.Context(), w)
+}
+
+type field struct {
+	text      string
+	validator func(string) error
+}
+
+var fields = map[string]field{
+	"email": {
+		text: "Email",
+		validator: func(value string) error {
+			if value != "test@test.com" {
+				return errors.New("Only test@test.com is valid.")
+			}
+			return nil
+		},
+	},
+	"firstName": {
+		text: "First Name",
+		validator: func(value string) error {
+			if value == "" {
+				return errors.New("Required")
+			}
+			return nil
+		},
+	},
+	"lastName": {
+		text: "Last Name",
+		validator: func(value string) error {
+			if value == "" {
+				return errors.New("Required")
+			}
+			return nil
+		},
+	},
+}
diff --git a/inlinevalidation/templates.templ b/inlinevalidation/templates.templ
new file mode 100644
index 0000000..c25dd6d
--- /dev/null
+++ b/inlinevalidation/templates.templ
@@ -0,0 +1,36 @@
+package inlinevalidation
+
+import 	"examples/shared"
+
+templ demo() {
+	<form hx-post="/inline-validation/contact">
+		@inp(fields["email"], "email", "", nil)
+		@inp(fields["firstName"], "firstName", "", nil)
+		@inp(fields["lastName"], "lastName", "", nil)
+		<div class="field">
+			<div class="control"><button class="button is-link">Submit</button></div>
+		</div>
+	</form>
+}
+
+templ inp(f field, name, value string, validation error) {
+	<div hx-target="this" hx-swap="outerHTML" class="field">
+		<label class="label">{ f.text }</label>
+		<div class="control"><input class="input"
+	if validation != nil {
+		class="is-danger"
+	}
+	name={ name } value={ value } hx-post={ "/inline-validation/validate/"+name }/></div>
+		if validation != nil {
+			<p class="help is-danger">{ validation.Error() }</p>
+		}
+	</div>
+}
+
+templ Index() {
+	@shared.Layout("Inline Validation") {
+		<h2 class="title">Inline Validation</h2>
+		@demo()
+	}
+}
+
diff --git a/inlinevalidation/templates_templ.go b/inlinevalidation/templates_templ.go
new file mode 100644
index 0000000..09d750c
--- /dev/null
+++ b/inlinevalidation/templates_templ.go
@@ -0,0 +1,381 @@
+// Code generated by templ@(devel) DO NOT EDIT.
+
+package inlinevalidation
+
+//lint:file-ignore SA4006 This context is only used if a nested component is present.
+
+import "github.com/a-h/templ"
+import "context"
+import "io"
+import "bytes"
+
+// GoExpression
+import 	"examples/shared"
+
+func demo() templ.Component {
+	return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
+		templBuffer, templIsBuffer := w.(*bytes.Buffer)
+		if !templIsBuffer {
+			templBuffer = templ.GetBuffer()
+			defer templ.ReleaseBuffer(templBuffer)
+		}
+		ctx = templ.InitializeContext(ctx)
+		var_1 := templ.GetChildren(ctx)
+		if var_1 == nil {
+			var_1 = templ.NopComponent
+		}
+		ctx = templ.ClearChildren(ctx)
+		// Element (standard)
+		_, err = templBuffer.WriteString("<form")
+		if err != nil {
+			return err
+		}
+		// Element Attributes
+		_, err = templBuffer.WriteString(" hx-post=\"/inline-validation/contact\"")
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString(">")
+		if err != nil {
+			return err
+		}
+		// TemplElement
+		err = inp(fields["email"], "email", "", nil).Render(ctx, templBuffer)
+		if err != nil {
+			return err
+		}
+		// TemplElement
+		err = inp(fields["firstName"], "firstName", "", nil).Render(ctx, templBuffer)
+		if err != nil {
+			return err
+		}
+		// TemplElement
+		err = inp(fields["lastName"], "lastName", "", nil).Render(ctx, templBuffer)
+		if err != nil {
+			return err
+		}
+		// Element (standard)
+		_, err = templBuffer.WriteString("<div")
+		if err != nil {
+			return err
+		}
+		// Element Attributes
+		_, err = templBuffer.WriteString(" class=\"field\"")
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString(">")
+		if err != nil {
+			return err
+		}
+		// Element (standard)
+		_, err = templBuffer.WriteString("<div")
+		if err != nil {
+			return err
+		}
+		// Element Attributes
+		_, err = templBuffer.WriteString(" class=\"control\"")
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString(">")
+		if err != nil {
+			return err
+		}
+		// Element (standard)
+		_, err = templBuffer.WriteString("<button")
+		if err != nil {
+			return err
+		}
+		// Element Attributes
+		_, err = templBuffer.WriteString(" class=\"button is-link\"")
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString(">")
+		if err != nil {
+			return err
+		}
+		// Text
+		var_2 := `Submit`
+		_, err = templBuffer.WriteString(var_2)
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString("</button>")
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString("</div>")
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString("</div>")
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString("</form>")
+		if err != nil {
+			return err
+		}
+		if !templIsBuffer {
+			_, err = io.Copy(w, templBuffer)
+		}
+		return err
+	})
+}
+
+func inp(f field, name, value string, validation error) templ.Component {
+	return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
+		templBuffer, templIsBuffer := w.(*bytes.Buffer)
+		if !templIsBuffer {
+			templBuffer = templ.GetBuffer()
+			defer templ.ReleaseBuffer(templBuffer)
+		}
+		ctx = templ.InitializeContext(ctx)
+		var_3 := templ.GetChildren(ctx)
+		if var_3 == nil {
+			var_3 = templ.NopComponent
+		}
+		ctx = templ.ClearChildren(ctx)
+		// Element (standard)
+		_, err = templBuffer.WriteString("<div")
+		if err != nil {
+			return err
+		}
+		// Element Attributes
+		_, err = templBuffer.WriteString(" hx-target=\"this\"")
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString(" hx-swap=\"outerHTML\"")
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString(" class=\"field\"")
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString(">")
+		if err != nil {
+			return err
+		}
+		// Element (standard)
+		_, err = templBuffer.WriteString("<label")
+		if err != nil {
+			return err
+		}
+		// Element Attributes
+		_, err = templBuffer.WriteString(" class=\"label\"")
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString(">")
+		if err != nil {
+			return err
+		}
+		// StringExpression
+		var var_4 string = f.text
+		_, err = templBuffer.WriteString(templ.EscapeString(var_4))
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString("</label>")
+		if err != nil {
+			return err
+		}
+		// Element (standard)
+		_, err = templBuffer.WriteString("<div")
+		if err != nil {
+			return err
+		}
+		// Element Attributes
+		_, err = templBuffer.WriteString(" class=\"control\"")
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString(">")
+		if err != nil {
+			return err
+		}
+		// Element (void)
+		_, err = templBuffer.WriteString("<input")
+		if err != nil {
+			return err
+		}
+		// Element Attributes
+		_, err = templBuffer.WriteString(" class=\"input\"")
+		if err != nil {
+			return err
+		}
+		if validation != nil {
+			// Element Attributes
+			_, err = templBuffer.WriteString(" class=\"is-danger\"")
+			if err != nil {
+				return err
+			}
+		}
+		_, err = templBuffer.WriteString(" name=")
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString("\"")
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString(templ.EscapeString(name))
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString("\"")
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString(" value=")
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString("\"")
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString(templ.EscapeString(value))
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString("\"")
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString(" hx-post=")
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString("\"")
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString(templ.EscapeString("/inline-validation/validate/"+name))
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString("\"")
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString(">")
+		if err != nil {
+			return err
+		}
+		_, err = templBuffer.WriteString("</div>")
+		if err != nil {
+			return err
+		}
+		// If
+		if validation != nil {
+			// Element (standard)
+			_, err = templBuffer.WriteString("<p")
+			if err != nil {
+				return err
+			}
+			// Element Attributes
+			_, err = templBuffer.WriteString(" class=\"help is-danger\"")
+			if err != nil {
+				return err
+			}
+			_, err = templBuffer.WriteString(">")
+			if err != nil {
+				return err
+			}
+			// StringExpression
+			var var_5 string = validation.Error()
+			_, err = templBuffer.WriteString(templ.EscapeString(var_5))
+			if err != nil {
+				return err
+			}
+			_, err = templBuffer.WriteString("</p>")
+			if err != nil {
+				return err
+			}
+		}
+		_, err = templBuffer.WriteString("</div>")
+		if err != nil {
+			return err
+		}
+		if !templIsBuffer {
+			_, err = io.Copy(w, templBuffer)
+		}
+		return err
+	})
+}
+
+func Index() templ.Component {
+	return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
+		templBuffer, templIsBuffer := w.(*bytes.Buffer)
+		if !templIsBuffer {
+			templBuffer = templ.GetBuffer()
+			defer templ.ReleaseBuffer(templBuffer)
+		}
+		ctx = templ.InitializeContext(ctx)
+		var_6 := templ.GetChildren(ctx)
+		if var_6 == nil {
+			var_6 = templ.NopComponent
+		}
+		ctx = templ.ClearChildren(ctx)
+		// TemplElement
+		var_7 := templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
+			templBuffer, templIsBuffer := w.(*bytes.Buffer)
+			if !templIsBuffer {
+				templBuffer = templ.GetBuffer()
+				defer templ.ReleaseBuffer(templBuffer)
+			}
+			// Element (standard)
+			_, err = templBuffer.WriteString("<h2")
+			if err != nil {
+				return err
+			}
+			// Element Attributes
+			_, err = templBuffer.WriteString(" class=\"title\"")
+			if err != nil {
+				return err
+			}
+			_, err = templBuffer.WriteString(">")
+			if err != nil {
+				return err
+			}
+			// Text
+			var_8 := `Inline Validation`
+			_, err = templBuffer.WriteString(var_8)
+			if err != nil {
+				return err
+			}
+			_, err = templBuffer.WriteString("</h2>")
+			if err != nil {
+				return err
+			}
+			// Whitespace (normalised)
+			_, err = templBuffer.WriteString(` `)
+			if err != nil {
+				return err
+			}
+			// TemplElement
+			err = demo().Render(ctx, templBuffer)
+			if err != nil {
+				return err
+			}
+			if !templIsBuffer {
+				_, err = io.Copy(w, templBuffer)
+			}
+			return err
+		})
+		err = shared.Layout("Inline Validation").Render(templ.WithChildren(ctx, var_7), templBuffer)
+		if err != nil {
+			return err
+		}
+		if !templIsBuffer {
+			_, err = io.Copy(w, templBuffer)
+		}
+		return err
+	})
+}
+
diff --git a/main.go b/main.go
index 1b58493..cba1c90 100644
--- a/main.go
+++ b/main.go
@@ -6,6 +6,7 @@ import (
 	"examples/clicktoload"
 	"examples/deleterow"
 	"examples/editrow"
+	"examples/inlinevalidation"
 	"examples/lazyload"
 	"log"
 	"net/http"
@@ -72,4 +73,10 @@ var examples = []Example{
 		Slug:     "lazy-loading",
 		Handlers: lazyload.Handlers,
 	},
+	{
+		Name:     "Inline Validation",
+		Desc:     "Demonstrates how to do inline field validation",
+		Slug:     "inline-validation",
+		Handlers: inlinevalidation.Handlers,
+	},
 }