templ-htmx
Build interactive hypermedia-driven applications with templ and HTMX. Use when creating dynamic UIs, real-time updates, AJAX interactions, mentions 'HTMX', 'dynamic content', or 'interactive templ app'.
Install
mkdir -p .claude/skills/templ-htmx && curl -L -o skill.zip "https://mcp.directory/api/skills/download/2562" && unzip -o skill.zip -d .claude/skills/templ-htmx && rm skill.zipInstalls to .claude/skills/templ-htmx
About this skill
Templ + HTMX Integration
Overview
HTMX enables modern, interactive web applications with minimal JavaScript. Combined with templ's type-safe components, you get fast, reliable hypermedia-driven UIs.
Key Benefits:
- No JavaScript framework needed
- Server-side rendering
- Minimal client-side code
- Progressive enhancement
- Type-safe components
When to Use This Skill
Use when:
- Building interactive UIs
- Creating dynamic content
- User mentions "HTMX", "dynamic updates", "real-time"
- Implementing AJAX-like behavior without JS
- Building SPAs without frameworks
Quick Start
1. Import and Mount HTMX
First, import the htmx package and mount it in your server:
import (
"within.website/x/htmx"
)
func main() {
mux := http.NewServeMux()
// Mount HTMX static files at /.within.website/x/htmx/
htmx.Mount(mux)
// ... other routes
}
2. Add HTMX to Layout
package components
import "within.website/x/htmx"
templ Layout(title string) {
<!DOCTYPE html>
<html>
<head>
<title>{ title }</title>
@htmx.Use()
</head>
<body>
{ children... }
</body>
</html>
}
The htmx.Use() component includes the core HTMX library. You can add extensions:
// Add SSE and path-params extensions
@htmx.Use("sse", "path-params")
Available extensions: event-header, path-params, remove-me, websocket.
3. Detect HTMX Requests
Use the htmx.Is() function to check if a request was made by HTMX:
import "within.website/x/htmx"
func handler(w http.ResponseWriter, r *http.Request) {
if htmx.Is(r) {
// Return partial HTML fragment for HTMX
components.Partial().Render(r.Context(), w)
} else {
// Return full page for direct navigation
components.FullPage().Render(r.Context(), w)
}
}
4. Create Interactive Component
templ Counter(count int) {
<div>
<p>Count: { strconv.Itoa(count) }</p>
<button
hx-post="/counter/increment"
hx-target="#counter"
hx-swap="outerHTML"
>
Increment
</button>
</div>
}
5. Create Handler
func incrementHandler(w http.ResponseWriter, r *http.Request) {
count := getCount() + 1
saveCount(count)
components.Counter(count).Render(r.Context(), w)
}
Core HTMX Attributes
hx-get / hx-post
Trigger HTTP requests:
templ SearchBox() {
<input
type="text"
name="q"
hx-get="/search"
hx-trigger="keyup changed delay:500ms"
hx-target="#results"
/>
<div id="results"></div>
}
Handler:
func searchHandler(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query().Get("q")
results := search(query)
components.SearchResults(results).Render(r.Context(), w)
}
hx-target
Specify where to insert response:
templ LoadMore(page int) {
<button
hx-get={ "/posts?page=" + strconv.Itoa(page) }
hx-target="#posts"
hx-swap="beforeend"
>
Load More
</button>
}
hx-swap
Control how content is swapped:
// innerHTML (default)
hx-swap="innerHTML"
// outerHTML - replace element itself
hx-swap="outerHTML"
// beforeend - append inside
hx-swap="beforeend"
// afterend - insert after
hx-swap="afterend"
hx-trigger
Control when requests fire:
// On click (default for buttons)
<button hx-get="/data">Click me</button>
// On change
<select hx-get="/filter" hx-trigger="change">
// On keyup with delay
<input hx-get="/search" hx-trigger="keyup changed delay:300ms">
// On page load
<div hx-get="/data" hx-trigger="load">
// Every 5 seconds
<div hx-get="/updates" hx-trigger="every 5s">
Common Patterns
Pattern 1: Live Search
Component:
templ SearchBox() {
<div>
<input
type="text"
name="q"
placeholder="Search..."
hx-get="/search"
hx-trigger="keyup changed delay:500ms"
hx-target="#search-results"
hx-indicator="#spinner"
/>
<span id="spinner" class="htmx-indicator">
Searching...
</span>
</div>
<div id="search-results"></div>
}
templ SearchResults(results []string) {
<ul>
for _, result := range results {
<li>{ result }</li>
}
</ul>
}
Handler:
func searchHandler(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query().Get("q")
results := performSearch(query)
components.SearchResults(results).Render(r.Context(), w)
}
Pattern 2: Infinite Scroll
templ PostList(posts []Post, page int) {
<div id="posts">
for _, post := range posts {
@PostCard(post)
}
</div>
if len(posts) > 0 {
<div
hx-get={ "/posts?page=" + strconv.Itoa(page+1) }
hx-trigger="revealed"
hx-swap="outerHTML"
>
Loading more...
</div>
}
}
Pattern 3: Delete with Confirmation
templ DeleteButton(itemID string) {
<button
hx-delete={ "/items/" + itemID }
hx-confirm="Are you sure?"
hx-target="closest tr"
hx-swap="outerHTML swap:1s"
>
Delete
</button>
}
Handler:
func deleteHandler(w http.ResponseWriter, r *http.Request) {
itemID := strings.TrimPrefix(r.URL.Path, "/items/")
deleteItem(itemID)
// Return empty to remove element
w.WriteHeader(http.StatusOK)
}
Pattern 4: Inline Edit
templ EditableField(id string, value string) {
<div id={ "field-" + id }>
<span>{ value }</span>
<button
hx-get={ "/edit/" + id }
hx-target={ "#field-" + id }
hx-swap="outerHTML"
>
Edit
</button>
</div>
}
templ EditForm(id string, value string) {
<form
hx-post={ "/save/" + id }
hx-target={ "#field-" + id }
hx-swap="outerHTML"
>
<input type="text" name="value" value={ value } />
<button type="submit">Save</button>
<button
hx-get={ "/cancel/" + id }
hx-target={ "#field-" + id }
>
Cancel
</button>
</form>
}
Pattern 5: Form Validation
templ SignupForm() {
<form hx-post="/signup" hx-target="#form-errors">
<div id="form-errors"></div>
<input
type="email"
name="email"
hx-post="/validate/email"
hx-trigger="blur"
hx-target="#email-error"
/>
<div id="email-error"></div>
<input type="password" name="password" />
<button type="submit">Sign Up</button>
</form>
}
templ ValidationError(message string) {
<span class="error">{ message }</span>
}
Pattern 6: Polling / Real-time Updates
templ LiveStats() {
<div
hx-get="/stats"
hx-trigger="load, every 5s"
hx-swap="innerHTML"
>
Loading stats...
</div>
}
templ StatsDisplay(stats Stats) {
<div>
<p>Users online: { strconv.Itoa(stats.UsersOnline) }</p>
<p>Active sessions: { strconv.Itoa(stats.Sessions) }</p>
</div>
}
Advanced Patterns
Out-of-Band Updates (OOB)
Update multiple parts of page:
templ CartButton(count int) {
<button id="cart-btn">
Cart ({ strconv.Itoa(count) })
</button>
}
templ AddToCartResponse(item Item) {
// Main response
<div class="notification">
Added { item.Name } to cart!
</div>
// Update cart button (different part of page)
<div id="cart-btn" hx-swap-oob="true">
@CartButton(getCartCount())
</div>
}
Progressive Enhancement
templ Form() {
<form
action="/submit"
method="POST"
hx-post="/submit"
hx-target="#result"
>
<input type="text" name="data" />
<button type="submit">Submit</button>
</form>
<div id="result"></div>
}
Works without JavaScript, enhanced with HTMX.
Loading States
templ DataTable() {
<div
hx-get="/data"
hx-trigger="load"
hx-indicator="#loading"
>
<div id="loading" class="htmx-indicator">
Loading data...
</div>
</div>
}
CSS:
.htmx-indicator {
display: none;
}
.htmx-request .htmx-indicator {
display: inline;
}
.htmx-request.htmx-indicator {
display: inline;
}
Response Headers
HX-Trigger
Trigger client-side events:
func handler(w http.ResponseWriter, r *http.Request) {
// Do work...
// Trigger custom event
w.Header().Set("HX-Trigger", "itemCreated")
components.Success().Render(r.Context(), w)
}
Client side:
document.body.addEventListener("itemCreated", function (evt) {
console.log("Item created!");
});
HX-Redirect
func handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("HX-Redirect", "/dashboard")
w.WriteHeader(http.StatusOK)
}
HX-Refresh
func handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("HX-Refresh", "true")
w.WriteHeader(http.StatusOK)
}
Special Status Code
Stop polling with status code 286:
import "within.website/x/htmx"
func pollHandler(w http.ResponseWriter, r *http.Request) {
if shouldStopPolling() {
w.WriteHeader(htmx.StatusStopPolling)
return
}
// ... return normal content
}
Request Headers
Access HTMX request headers:
import "within.website/x/htmx"
func handler(w http.ResponseWriter, r *http.Request) {
// Check if this is an HTMX request
if htmx.Is(r) {
// Get user's response to hx-prompt
promptResponse := r.Header.Get(htmx.HeaderPrompt)
}
}
Content truncated.
More by Xe
View all skills by Xe →You might also like
flutter-development
aj-geddes
Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design.
drawio-diagrams-enhanced
jgtolentino
Create professional draw.io (diagrams.net) diagrams in XML format (.drawio files) with integrated PMP/PMBOK methodologies, extensive visual asset libraries, and industry-standard professional templates. Use this skill when users ask to create flowcharts, swimlane diagrams, cross-functional flowcharts, org charts, network diagrams, UML diagrams, BPMN, project management diagrams (WBS, Gantt, PERT, RACI), risk matrices, stakeholder maps, or any other visual diagram in draw.io format. This skill includes access to custom shape libraries for icons, clipart, and professional symbols.
ui-ux-pro-max
nextlevelbuilder
"UI/UX design intelligence. 50 styles, 21 palettes, 50 font pairings, 20 charts, 8 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, mobile app, .html, .tsx, .vue, .svelte. Elements: button, modal, navbar, sidebar, card, table, form, chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, flat design. Topics: color palette, accessibility, animation, layout, typography, font pairing, spacing, hover, shadow, gradient."
godot
bfollington
This skill should be used when working on Godot Engine projects. It provides specialized knowledge of Godot's file formats (.gd, .tscn, .tres), architecture patterns (component-based, signal-driven, resource-based), common pitfalls, validation tools, code templates, and CLI workflows. The `godot` command is available for running the game, validating scripts, importing resources, and exporting builds. Use this skill for tasks involving Godot game development, debugging scene/resource files, implementing game systems, or creating new Godot components.
nano-banana-pro
garg-aayush
Generate and edit images using Google's Nano Banana Pro (Gemini 3 Pro Image) API. Use when the user asks to generate, create, edit, modify, change, alter, or update images. Also use when user references an existing image file and asks to modify it in any way (e.g., "modify this image", "change the background", "replace X with Y"). Supports both text-to-image generation and image-to-image editing with configurable resolution (1K default, 2K, or 4K for high resolution). DO NOT read the image file first - use this skill directly with the --input-image parameter.
fastapi-templates
wshobson
Create production-ready FastAPI projects with async patterns, dependency injection, and comprehensive error handling. Use when building new FastAPI applications or setting up backend API projects.
Related MCP Servers
Browse all serversAccess 135+ animated React UI components from ReactBits.dev with intelligent caching, dependency detection, and quality
XcodeBuild streamlines iOS app development for Apple developers with tools for building, debugging, and deploying iOS an
Enhance productivity with AI-driven Notion automation. Leverage the Notion API for secure, automated workspace managemen
Unlock browser automation studio with Browserbase MCP Server. Enhance Selenium software testing and AI-driven workflows
Unlock powerful text to speech and AI voice generator tools with ElevenLabs. Create, clone, and customize speech easily.
Use Firebase to integrate Firebase Authentication, Firestore, and Storage for seamless backend services in your apps.
Stay ahead of the MCP ecosystem
Get weekly updates on new skills and servers.