README.md
April 19, 2026 ยท View on GitHub
"There is nothing new under the sun." โ Ecclesiastes.
โ๏ธ Features
This tool is extremely small and minimalistic, with absolutely no bells or whistles.
- Generates a shared HTML shell template that bootstraps any Scala.js view.
- Selects the correct view at request time by injecting its exported name into the template.
- Supports automatic hot reload during development via a WebSocket heartbeat.
โฌ๏ธ Installation
Choose one server integration and one client integration from the sections below โ that's all you need.
Compiled with Scala 3.8.3, with no intention to explicitly support older versions.
โ๏ธ Example
Server
Define a ViewData for each page, then wire it up to a Tapir endpoint using showView:
import com.alecdorrington.pageloader.ViewData
import com.alecdorrington.pageloader.tapir.{HeartbeatService, ViewEndpoint}
val indexView = ViewData(name = "IndexView", pageTitle = "Home")
val aboutView = ViewData(name = "AboutView", pageTitle = "About")
val heartbeat = HeartbeatService[IO]()
val endpoints = List(
endpoint.get.in("").showView(indexView),
endpoint.get.in("about").showView(aboutView),
) ++ heartbeat.api
Client
Each view is a Scala.js object exported with @JSExportTopLevel. The name passed to the annotation must match the name field of the corresponding ViewData on the server.
import com.raquo.laminar.api.L.{*, given}
import com.alecdorrington.pageloader.laminar.LaminarView
import scala.scalajs.js.annotation.JSExportTopLevel
@JSExportTopLevel("IndexView")
object IndexView extends LaminarView:
override def content = div(
h1("Welcome to my website!"),
p("We're still getting set up here... Stay tuned!"),
)
๐ก Server Integration
Currently, a connector exists for only a single web framework: Tapir.
In principle, any future connectors will be published as separate dependencies with the name page-loader-{web-framework}.
Contributions are welcome!
Tapir
Tapir is a library to describe HTTP APIs and expose them as a server. A separate connector is provided to easily attach a ViewData to a Tapir endpoint. Add the following dependency:
libraryDependencies += "com.alecdorrington" %% "page-loader-tapir" % "0.2.2"
Use the showView extension method to convert any Tapir GET endpoint into one that serves a page:
endpoint.get.in("").showView(ViewData(name = "IndexView", pageTitle = "Home"))
Hot Reload
HeartbeatService exposes a WebSocket endpoint that the client connects to. When the server restarts, the disconnection is detected and the page reloads automatically. This is enabled by default when using showView.
val heartbeat = HeartbeatService[IO]()
// Add heartbeat.api to your server alongside your page endpoints.
To disable hot reload for a specific page, pass hotReloadWebsocketPath = None:
endpoint.get.in("").showView(view, hotReloadWebsocketPath = None)
๐จ Client Integration
Currently, a connector exists for only a single UI framework: Laminar.
In principle, any future connectors will be published as separate dependencies with the name page-loader-{ui-framework}.
Contributions are welcome!
Laminar
Laminar is a reactive UI library for Scala.js. A separate connector provides LaminarView, a base trait that handles rendering automatically. Add the following dependency:
libraryDependencies += "com.alecdorrington" %%% "page-loader-laminar" % "0.2.2"
Extend LaminarView and implement content:
import com.raquo.laminar.api.L.{*, given}
import com.alecdorrington.pageloader.laminar.LaminarView
import scala.scalajs.js.annotation.JSExportTopLevel
@JSExportTopLevel("IndexView")
object IndexView extends LaminarView:
override def content = div(
h1("Welcome to my website!"),
p("We're still getting set up here... Stay tuned!"),
)
๐๏ธ See also
- See Scala Website Template for an example template which uses Page Loader to build a full stack website.
- See Asset Loader for a similar library which loads static assets instead of dynamic pages.
- This library was made using Scala Library Template.