Skip to content

Instantly share code, notes, and snippets.

@maxsei
Created June 17, 2026 20:06
Show Gist options
  • Select an option

  • Save maxsei/6cc69bd0f3f8562c68f36589b2e4d7f2 to your computer and use it in GitHub Desktop.

Select an option

Save maxsei/6cc69bd0f3f8562c68f36589b2e4d7f2 to your computer and use it in GitHub Desktop.
delay showing load spinner with datastar
package main
import (
"log"
"math/rand"
"net/http"
"time"
"github.com/starfederation/datastar-go/datastar"
)
const indexHtml = `
<html>
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>App</title>
<ViteClient />
<link rel="icon" type="image/x-icon" href="/favicon.png" />
<link
rel="stylesheet"
href="https://unpkg.com/open-props@1.7.23/open-props.min.css"
/>
<link rel="stylesheet" href="/style.css" />
<script
src="https://cdn.jsdelivr.net/gh/starfederation/datastar@1.0.2/bundles/datastar.js"
type="module"
integrity="sha384-SnyFlWTdFL3c8+9/1WsPuMFBq6AQOGC1LmS9upY4YkM3En3wZr5q2UvydHaMgOVG"
crossorigin="anonymous"
></script>
</head>
<body>
<div
data-signals="{message: '', count: 0}"
>
<button
id="loadBtn"
data-indicator:_fetching
data-signals:_showLoading=""
data-on:datastar-fetch__delay.200ms="$_showLoading = evt.detail.type === 'started'"
data-computed:_show="$_showLoading && $_fetching"
data-on:click="@get('/api/update')"
>
Get Update
</button>
<div data-show="$_show" style="display: none">Loading…</div>
<pre data-json-signals></pre>
</div>
</body>
</html>
`
type Store struct {
Message string `json:"message"`
Count int `json:"count"`
}
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){
w.Header().Set("Content-Type", "text/html")
if _, err := w.Write([]byte(indexHtml)); err != nil {
log.Printf("Error writing index html: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
})
store := &Store{}
http.HandleFunc("/api/update", func(w http.ResponseWriter, r *http.Request) {
if err := datastar.ReadSignals(r, store); err != nil {
log.Printf("Error reading update signals: %v", err)
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
time.Sleep(time.Millisecond * 1000 + 0 * time.Duration(rand.Intn(1000)))
sse := datastar.NewSSE(w, r)
sse.MarshalAndPatchSignals(map[string]any{
"message": "Updated message",
"count": store.Count + 1,
})
})
port := "8080"
log.Printf("listening and serving at: http://localhost:%s", port)
http.ListenAndServe(":8080", nil)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment