class: center, middle, inverse # Scala and HTMX for Simpler Web Development
by Sakib Hadžiavdić
--- # Who am I? ### Sakib Hadžiavdić - Based in Sarajevo, Bosnia 🇧🇦 - Software Engineer @ [SaCode](https://sacode.dev) - Doing OSS work: FlowRun, Hepek, Sharaf... https://github.com/sake92 --- class: center, middle, inverse # Scala a programming language that scales with you --- # Scala: TLDR - the **best programming language** (JVM, JS, WASM, Native) - FP - immutability, ADTs - pattern matching - type classes - OOP - classes, objects etc - scala-cli for scripting --- # Sharaf 🔩 - minimalistic framework in Scala 3 - "direct style" (no async complexities..) - "batteries included" - based on Undertow (but supports Helidon too!) - https://sake92.github.io/sharaf/ --- ## Sharaf: Hello World ```scala //> using scala 3.7.0 //> using dep ba.sake::sharaf-undertow:0.13.0 import ba.sake.sharaf.* import ba.sake.sharaf.undertow.UndertowSharafServer val routes = Routes { case GET -> Path("hello", name) => Response.withBody(s"Hello $name") } UndertowSharafServer("localhost", 8181, routes).start() println(s"Server started at http://localhost:8181") ``` --- ## Sharaf: benefits ```scala case GET -> Path("files", segments*) => ??? case GET -> Path("files", "abc.txt") => ??? // Unreachable case // typesafe extract path params, DRY case GET -> Path("cars", param[Int](carId)) => ??? // also enums, regexes... ``` --- ## Sharaf: benefits Lightweight "dependency injection": ```scala // context function, "implicit function" // Kotlin's "Context Receivers" type Routes = Request ?=> PartialFunction[RequestParams, Response[?]] Routes { case GET -> Path("files", segments*) => Request.current // only available inside Routes{} ! } // utilities, session impl etc.. def currentUser(using req: Request): User = ``` --- ## Sharaf: Serving HTML - pure scala, safe interpolation! - no files, no template language ```scala val routes = Routes { case GET -> Path() => Response.withBody(IndexView) } def IndexView = html""" <!DOCTYPE html> <html lang="en"> <body> <div> <p>Welcome!</p> <a href="/hello/Bob">Hello world</a> </div> </body> </html> """ ``` --- ## Query Params ```scala case GET -> Path("query-params") => case class SearchParams(q: String, perPage: Int) derives QueryStringRW val qp = Request.current.queryParams[SearchParams] Response.withBody(s"Got query params: ${qp}") ``` ## Forms ```scala case POST -> Path("handle-form") => case class ContactUsForm(fullName: String, email: String) derives FormDataRW val formData = Request.current.bodyForm[ContactUsForm] Response.withBody(s"Got form data: ${formData}") ``` ## JSON ```scala case POST -> Path("handle-json") => case class MyRequest(fullName: String, email: String) derives JsonRW val jsonData = Request.current.bodyForm[MyRequest] Response.withBody(s"Got JSON data: ${jsonData}") ``` --- class: center, middle, inverse # State of the WEB --- background-image: url(content/MPA.png) # WEB dev before - HTML built in PHP, JSP.. all server side - CSS
- sprinkle of (messy) jQuery
```jsp
Temp goes here
...... ``` ```js $.ajax({ url: "/api/getWeather", data: { zipcode: 97201 }, success: function(result) { $("#weather-temp").html("
" + result + "
degrees"); } }); ``` --- background-image: url(content/SPA.png) # WEB dev now - React, Vue, Angular - bundlers, minifiers - build tools, compilers..
- server-rendering is back?? kinda but not really --- # What WEB/HTML should be? 💡 - why only `
` & `
` make HTTP requests? - why only `GET` & `POST` methods? - why only `click` & `submit` events? - why only replace the **entire screen**? --- class: center, middle, inverse # HTMX High power tools for HTML --- background-image: url(content/HTMX.png) background-position: right # HTMX: TLDR - HTML-first, server-first library - works with **any backend** - progressive enhancement - no build tools needed - awesome community + memes 🐴
- very popular! https://risingstars.js.org/2024/en#section-framework --- background-image: url(content/the_floor_js.jpg) ## HTMX: in a nutshell --- background-image: url(content/htmx_protec.jpg) ## HTMX: in a nutshell --- ## HTMX + Scala 🚀 ```scala val routes = Routes { case GET -> Path() => Response.withBody(IndexView) case POST -> Path("html-snippet") => Response.withBody( html"""
Look ma, no JS! 😎
""" ) } def IndexView = html""" <!DOCTYPE html> <html> <head> <script src="/htmx.min.js"></script> </head> <body> <button hx-trigger="click" hx-post="/html-snippet" hx-swap="outerHTML"> Click here! </button> </body> </html> """ ``` --- ## HTMX: demo time! - demo1: Hello world - demo2: Notes app - demo3: Server Sent Events
http://localhost:8181/ --- # RESTful APIs: HATEOAS - Hypermedia as the Engine of Application State - HTML == Hypermedia - state representation + controls/actions - "widgets" all the way
- browser is the *ultimate* (universal) thick client - browser is one "SPA" to rule them all --- ## HTMX: even more power 🛠️ - lazy loading, infinite scroll, request indicator.. - active search, cascading selects - polling, throttling, filtering trigger events - dialogs, tabs - animations - out of band swaps - boosting - integrates well with JS libraries --- ## HTMX: benefits ✅ - no API churn (backend for frontend) - less security issues VS e.g. GraphQL - less code to maintain (67% less [vs React](https://htmx.org/essays/a-real-world-react-to-htmx-port/)) - less dependencies (96% [vs React](https://htmx.org/essays/a-real-world-react-to-htmx-port/)) - reduced time-to-interactive etc - less (no?) build time - less memory usage - more power to the BE, less state in FE --- ## HTMX: limitations 🙅 - many dynamic interdependencies (Excel) - offline mode - lots of events - e.g. google sheets, maps, games.. --- class: inverse-really background-image: url(content/explorers.png) # Brave Explorers Scala and HTMX are like brave explorers. They **explore the limits of what is possible**. And everyone benefits from these findings! --- class: center, middle # Conclusion Try HTMX for a bit of fresh air! Try scala for fun and profit!
https://htmx.org https://grugbrain.dev https://scala-lang.org https://github.com/sake92/sharaf
Thanks for listening! --- # Extras ## Error handling https://htmx.org/extensions/response-targets/ https://dev.to/yawaramin/handling-form-errors-in-htmx-3ncg