Guestbook (Datastar)
A working guestbook powered by Datastar (opens in new tab) and server-sent events. Search, add entries, and edit inline — all without page reloads.
If you can read, you can cook. If you know Go, you can use Gastro.
I don't really know what I'm doing, but the file-based routing makes it easy.
Anyone can cook... and anyone can build web apps with Gastro!
How It Works
This demo showcases four common hypermedia patterns using Datastar and Gastro's SSE support.
Search-as-you-type
The search input uses data-bind to create a reactive signal and data-on:input__debounce.300ms to send a debounced request. The server filters entries and patches the list:
<input
data-bind:search
data-on:input__debounce.300ms="@get('/api/ds/search')"
data-indicator:searching
>
Form Submission
The form uses data-on:submit to intercept submission and send the data via Datastar's @post. The server validates, adds the entry, and patches both the list and the form:
func handleDsAdd(w http.ResponseWriter, r *http.Request) {
name := strings.TrimSpace(r.FormValue("name"))
message := strings.TrimSpace(r.FormValue("message"))
demo.AddEntry(name, message)
// Patch the list with new entries
sse := datastar.NewSSE(w, r)
sse.PatchElements(listHTML)
// Patch the form with a success message
sse.PatchElements(formHTML)
}
Inline Editing
Each entry has an edit button that sends @get('/api/ds/edit/{id}'). The server returns a GuestbookEntryEdit component that replaces the read-only row. Saving sends @post('/api/ds/save/{id}') and swaps back to the read-only view.
Loading States
The data-indicator attribute creates a boolean signal that's true while a request is in flight. Combined with data-show and data-attr:disabled, this provides visual feedback without any JavaScript:
<button data-indicator:submitting data-attr:disabled="$submitting">
<span data-show="!$submitting">Sign Guestbook</span>
<span data-show="$submitting">Sending...</span>
</button>