The last thing I wanted to explore is how the usability and performance of the application can be improved by means of some client-side enhancements. By default, a web app rendered on the server-side like ours requires full page loads when going from one page to the other. This is where single page applications (SPAs) implemented with client-side frameworks shine: just parts of the document object model tree in the browser will be replaced e.g. when loading a result list via AJAX, resulting in a much smoother and faster user experience.

Does this mean we have to give up on server-side rendering altogether if we’re after this kind of UX? Luckily not, as small helper libraries such as Unpoly, Intercooler or Turbolinks can be leveraged to replace just page fragments instead of requiring full page loads. This results in a smooth SPA-like user experience without having to opt into the full client-side programming model. For the Todo example I’ve obtained great results using Unpoly. After importing its JavaScript file, all that’s needed is to add the up-target attribute to links or forms.

E.g. here’s the form for entering the search term with that modification:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 (1) <form action= "/todo" method= "GET" name= "search" up-target= ".container" > <div class= "form-row align-items-center" > <div class= "col-sm-3 my-1" > <label class= "sr-only" for= "filter" > Search </label> <input type= "text" name= "filter" class= "form-control" id= "filter" placeholder= "Search By Title" required { #if filtered } value= "{filter}" {/ if } > </div> <input class= "btn btn-primary" value= "Search" type= "submit" > (2) <a class= "btn btn-secondary {#if !filtered}disabled{/if}" href= "/todo" role= "button" up-target= ".container" > Clear Filter </a> </div> </form>

1 When receiving the result of the form submission, replace the <div> with CSS class container of the current page with the one from the response 2 Do the same when following the "Clear Filter" link

The magic trick of Unpoly is that links and forms with the up-target attribute are intercepted by Unpoly and executed via AJAX calls. The specified fragments from the result page are then used to replace parts of the already loaded page, instead of having the browser load the full response page. The result is the fast user experience shown in the video above.

Unpoly also allows to show page fragments in modal dialogs, allowing to remain on the same page also when showing forms such as the one for editing a todo: