No description
  • Scala 97.8%
  • JavaScript 1.8%
  • Shell 0.2%
  • Nix 0.2%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Paul-Henri Froidmont 8b8913cdea
Some checks failed
Publish snapshot / deploy-documentation (push) Has been cancelled
Publish snapshot / publish (push) Has been cancelled
merge: visit only changed components, cut kept-row costs and share component statics (#10, #11, #12)
2026-10-29 11:34:01 +01:00
.github/workflows ci: do not run the benchmark regression check on shared runners 2026-10-24 23:55:37 +02:00
benchmarks perf(benchmarks): refresh the regression baseline after the turn cost work (#10) 2026-10-29 11:25:50 +01:00
docs docs(performance): record what a stream of components and a targeted turn still cost (#10) 2026-10-29 11:16:32 +01:00
documentation feat(render): keep static composite tokens in the template (#9) 2026-10-29 01:22:07 +01:00
e2eApp refactor(e2e): name the data of key-derived and split-class rows entries (#7) 2026-10-29 01:54:41 +01:00
rootSliceApp test(root-slice): scope the guarded page's guard to any navigation 2026-10-22 03:32:38 +02:00
scalive fix(transport): report no joined view once a transport has closed 2026-10-29 11:20:32 +01:00
scripts feat(forms): add blur-aware feedback bindings 2026-09-10 11:29:35 +02:00
test feat!: align with Phoenix LiveView 1.2.12 2026-10-19 19:24:12 +02:00
.envrc feat!: align with Phoenix LiveView 1.2.10 2026-08-26 19:31:15 +02:00
.gitignore fix(runtime): stabilize browser crash recovery 2026-08-21 17:35:41 +02:00
.scalafix.conf Configure scalafix 2025-11-07 05:10:10 +01:00
.scalafmt.conf build(deps): update Mill dependencies 2026-08-22 02:31:33 +02:00
AGENTS.md docs(agents): configure issue tracker, triage labels and domain docs for skills 2026-10-28 09:01:25 +01:00
build.mill fix(render): record kept rows without their components' renders 2026-10-25 02:58:52 +01:00
DomDefsGenerator.mill feat(html): inline SVG, newer attributes and a names table 2026-10-21 19:33:36 +02:00
flake.lock feat!: align with Phoenix LiveView 1.2.12 2026-10-19 19:24:12 +02:00
flake.nix feat!: align with Phoenix LiveView 1.2.12 2026-10-19 19:24:12 +02:00
GLOSSARY.md docs: record row function key decision and glossary 2026-10-28 10:27:15 +01:00
LICENSE docs: add MIT license 2026-08-15 00:20:01 +02:00
NpmAssets.mill feat(assets)!: support complete asset graphs 2026-08-31 00:54:01 +02:00
README.md ci: do not run the benchmark regression check on shared runners 2026-10-24 23:55:37 +02:00

Scalive

Publish snapshot Documentation License

Live interfaces. Typed end to end.

Scalive is a Scala 3 reimplementation of the Phoenix LiveView programming model. It keeps application state, rendering, and effects on the server, handles browser interactions as typed messages, and sends efficient HTML updates through the Phoenix LiveView client.

Scalive provides Scala-first APIs for typed models, messages, routes, forms, components, and HTML, with ZIO for effects. It targets observable LiveView behavior and feature coverage rather than Phoenix source or API compatibility.

Warning

Scalive is alpha software. APIs may change without compatibility shims, and feature coverage and production maturity are still evolving. Review the project status and compatibility matrix before use.

A LiveView In Scala

import scalive.*
import zio.{Task, ZIO}

final class CounterLiveView extends LiveView[CounterLiveView.Msg, Int]:
  import CounterLiveView.Msg

  def mount(ctx: MountContext): Task[Int] =
    ZIO.succeed(0)

  def handleMessage(model: Int, ctx: MessageContext) =
    case Msg.Decrement => ZIO.succeed(model - 1)
    case Msg.Increment => ZIO.succeed(model + 1)

  def view(model: Signal[Int]): HtmlElement[Msg] =
    mainTag(
      h1("Scalive counter"),
      button(typ := "button", on.click(Msg.Decrement), "Decrease"),
      outputTag(aria.live := "polite", model.map(_.toString)),
      button(typ := "button", on.click(Msg.Increment), "Increase")
    )

object CounterLiveView:
  enum Msg:
    case Decrement, Increment

Run the counter or build it from scratch.

Start Here

Development

Enter the repository development environment and run the common checks:

nix develop
mill __.reformat + __.fix
mill __.test
mill documentation.check

After a public API change, run mill documentation.pipeline.updateApiSnapshot to accept the new API. After a browser-visible change, run the browser suites with ./scripts/e2e-run-upstream.sh and ./scripts/e2e-run-e2e-app.sh. After a change to rendering, encoding or the runtime, run mill benchmarks.checkRegressions, which compares allocation and retained heap with a baseline; run mill benchmarks.updateRegressionBaseline to accept an intended change.

The Nix shell also provides the hash-pinned Phoenix client resources required by the Mill build. Run maintainer builds inside nix develop; published artifacts remain self-contained and impose no Nix requirement on application consumers.

Each checkout runs its own Mill daemon. Its heap is capped in the build.mill header (mill-jvm-opts), which also makes it return unused heap to the system when idle. The JVMs the build forks are capped too: tests through ScaliveTests.forkArgs, and run, runBackground, JMH benchmarks and the documentation tools through ScalaCommon.forkArgs, which the browser-test apps override.

The snapshot workflow also runs the root-slice and upstream Phoenix LiveView browser suites.

Report bugs, missing behavior, and focused feature requests through GitHub issues.

License

Scalive is available under the MIT License.