Hypermedia
Andurel v2.0.0-beta.1 has no hypermedia package. There is no pkg/hypermedia, no Datastar runtime, and no server-sent-event helpers. This page is kept so an existing link to it still explains where that behavior went.
The change is deliberate: a generated application has one page layer, Inertia, instead of two competing ones. Templ is still used, but only for the Inertia root document and email templates.
What replaced what
| Old approach | In v2.0.0-beta.1 |
|---|---|
Templ pages rendered by pkg/hypermedia |
Inertia pages under resources/js/Pages/, rendered by pkg/inertia |
| Datastar element and signal patches | Inertia visits, partial reloads, deferred props, and merge/scroll props |
| SSE streams built from patch helpers | No framework helper; use net/http directly when a stream is genuinely needed |
| Templ fragments for partial HTML | React components and Inertia partial reloads |
| Plain HTML responses | anduin.HTML or anduin.HTMLBlob |
The former files (internal/hypermedia, assets/js/datastar_*.js, Templ page views, and their controllers) are not part of the new scaffold. Nothing from them needs to be ported.
Templ in v2
Templ remains in exactly two places:
resources/root.templrenders the Inertia document shell.email/*.templdefines transactional email, compiled withandurel sync email.
Everything a visitor sees inside the document is a React component. See Views for that split and Inertia for the protocol.
Plain HTML responses
When an endpoint really is HTML and not an Inertia page, return it through the HTTP package. Handlers still take a context and return an error:
1func (h FeedHandler) Promo(ctx context.Context) error {
2 return anduin.HTML(ctx, http.StatusOK, "<h1>Launch week</h1>")
3}
anduin.HTMLBlob writes pre-rendered bytes. Keep these endpoints for non-page responses such as feeds, embeds and webhooks; do not build a second page layer with them.
Streaming responses
There is no Broadcaster, PatchComponent, or signal helper to call. If an endpoint must stream, write it with net/http:
1func (h StreamHandler) Events(ctx context.Context) error {
2 writer := anduin.ResponseWriter(ctx)
3 flusher, ok := writer.(http.Flusher)
4 if !ok {
5 return anduin.Error(ctx, http.StatusInternalServerError, errors.New("streaming unsupported"))
6 }
7
8 anduin.SetHeader(ctx, "Content-Type", "text/event-stream")
9 anduin.SetHeader(ctx, "Cache-Control", "no-cache")
10
11 for event := range h.events {
12 if _, err := fmt.Fprintf(writer, "data: %s\n\n", event); err != nil {
13 return err
14 }
15 flusher.Flush()
16 }
17
18 return nil
19}
Streams are the application's responsibility: observe the request context, bound the server write timeout, and make sure any proxy in front of the app does not buffer the response.
Migrating an old page
- Move the screen to a component under
resources/js/Pages/and render it withrenderer.Page. - Replace Datastar state with component state, props, and partial reloads.
- Move server data loading into a domain or service call from the handler.
- Delete
pkg/hypermediaimports, Datastar scripts, and Templ page files. - Run
andurel verifyandandurel sync payloadswhen a handler payload changed.