# Stack Research: SummerCMS

**Project:** SummerCMS - Scala CMF rewriting WinterCMS
**Researched:** 2026-02-04
**Overall Confidence:** HIGH (all major recommendations verified with official sources)

## Executive Summary

The ZIO ecosystem in 2025/2026 is mature and production-ready. ZIO HTTP 3.x is stable, Quill provides excellent PostgreSQL integration, and the tooling ecosystem (Mill, Besom) has reached 1.0 stability. The recommended stack prioritizes developer experience while maintaining the performance goals of the project.

**Key finding:** The ZIO ecosystem has consolidated around a smaller set of well-maintained libraries, with zio-sql and zio-jdbc deprecated in favor of Quill as the primary database library.

---

## Recommended Stack

### Language & Runtime

| Technology | Version | Purpose | Rationale |
|------------|---------|---------|-----------|
| Scala | 3.3.7 LTS | Core language | LTS provides stability for a multi-year project; 3.8.x requires JDK 17+ which may limit deployment options |
| JDK | 21+ | Runtime | LTS (Sept 2023), Loom virtual threads benefit JDBC blocking operations in Quill |
| ZIO | 2.1.24 | Effect system | Latest stable with stream performance improvements, binary compatibility guaranteed in 2.x line |

**Confidence:** HIGH - Verified via [Scala releases](https://www.scala-lang.org/download/all.html), [ZIO releases](https://github.com/zio/zio/releases)

**Notes:**
- Scala 3.3.7 LTS is recommended over 3.8.x bleeding edge - CMF needs stability over newest features
- ZIO 2.1.x line has explicit binary compatibility guarantees, critical for plugin ecosystem
- JDK 21+ for Loom virtual threads: While ZIO provides its own fiber system, Quill uses JDBC which does blocking I/O. Virtual threads make these blocking calls "virtually" non-blocking at the JVM level. ZIO can use virtual thread executors for blocking operations, complementing ZIO fibers rather than replacing them.

---

### Core Framework

| Technology | Version | Purpose | Rationale |
|------------|---------|---------|-----------|
| ZIO HTTP | 3.8.1 | HTTP server/client | Production-ready, built on Netty, native ZIO integration, OpenAPI support, built-in template DSL |

**Confidence:** HIGH - Verified via [ZIO HTTP releases](https://github.com/zio/zio-http/releases)

**Why ZIO HTTP over alternatives:**
- **vs http4s:** ZIO HTTP is ZIO-native; http4s is Cats Effect-native. Mixing ecosystems adds complexity.
- **vs Akka HTTP:** Licensing changes in Akka make it unsuitable for new projects.
- **vs Play:** Too heavyweight for a CMF, brings its own conventions that conflict with our plugin architecture.

**Key ZIO HTTP 3.x features for CMF:**
- Declarative endpoint definitions (maps to YAML-driven form generation)
- Built-in OpenAPI generation (API documentation for plugins)
- Middleware composition (authentication, logging, metrics)
- WebSocket support (future real-time features)
- Datastar SDK (new in 3.6.0 - alternative to HTMX, evaluate later)

---

### Database Layer

| Technology | Version | Purpose | Rationale |
|------------|---------|---------|-----------|
| ZIO Quill | 4.8.6 | Query DSL & ORM-like features | Compile-time query generation, ZIO-native contexts, PostgreSQL-specific features |
| PostgreSQL Driver | 42.7.5 | JDBC driver | Latest version compatible with Quill |
| HikariCP | 5.x | Connection pooling | Industry standard, ZIO integration via Quill contexts |
| Flyway | 10.x | Database migrations | Industry standard, straightforward ZIO integration |

**Confidence:** HIGH - Verified via [Quill documentation](https://zio.dev/zio-quill/), [Quill releases](https://github.com/zio/zio-quill/releases)

**Why Quill:**
- **zio-sql deprecated:** Per [Ziverge 2025 roadmap](https://www.ziverge.com/post/zio-in-2025), zio-sql and zio-jdbc are deprecated. Quill is the endorsed solution.
- **Compile-time queries:** SQL errors caught at compile time, critical for plugin ecosystem stability
- **ZIO contexts:** `PostgresZioJdbcContext` provides native ZIO effect integration
- **ProtoQuill:** Full Scala 3 support via zio-protoquill

**Installation:**
```scala
libraryDependencies ++= Seq(
  "io.getquill" %% "quill-jdbc-zio" % "4.8.6",
  "org.postgresql" % "postgresql" % "42.7.5",
  "org.flywaydb" % "flyway-core" % "10.22.0",
  "org.flywaydb" % "flyway-database-postgresql" % "10.22.0"
)
```

---

### Template Engine

| Technology | Version | Purpose | Rationale |
|------------|---------|---------|-----------|
| ScalaTags | 0.13.1 | Primary HTML generation | Type-safe, 4x faster than Twirl, pure Scala |
| Twirl | 2.0.9 | Theme templates (fallback) | Familiar syntax for theme developers, Play-compatible |

**Confidence:** MEDIUM - ScalaTags is well-documented; theme developer experience needs validation

**Primary approach: ScalaTags**
- Type-safe HTML construction
- [Almost 4x faster than Twirl](https://com-lihaoyi.github.io/scalatags/)
- Pure Scala - IDE support, refactoring works
- Integrates with ZIO HTTP's built-in template DSL
- Good for component rendering where type-safety matters

**Secondary approach: Twirl for themes**
- Theme developers expect template syntax, not Scala code
- Twirl's `@` syntax is intuitive for non-Scala developers
- Can be compiled at build time for performance
- Familiar to WinterCMS/Laravel Blade developers

**Hybrid strategy:**
- Core components and admin backend: ScalaTags (developer maintains, type-safety critical)
- Theme partials and layouts: Twirl (theme developers, simplicity matters)
- Consider: Custom template language (like Twig) parsed to ScalaTags at compile time

**Open question:** Should we invest in a Twig-to-ScalaTags compiler for WinterCMS theme compatibility?

---

### Frontend Integration

| Technology | Version | Purpose | Rationale |
|------------|---------|---------|-----------|
| HTMX | 2.x (latest) | Data-attribute driven interactions | Captures OctoberCMS data-attributes spirit, no build step, server-rendered |
| htmx4s | 0.3.0 | Scala HTMX integration | Type-safe HTMX attributes, ZIO HTTP compatible |
| Vue.js | 3.x | Complex interactive components | For forms, media manager, admin UI where HTMX insufficient |

**Confidence:** HIGH - htmx4s verified via [Scaladex](https://index.scala-lang.org/eikek/htmx4s), patterns validated via [Rock the JVM demo](https://github.com/rockthejvm/scalatags-htmx-demo)

**htmx4s modules:**
```scala
libraryDependencies ++= Seq(
  "com.github.eikek" %% "htmx4s-constants" % "0.3.0",    // HTMX vocabulary as Scala values
  "com.github.eikek" %% "htmx4s-scalatags" % "0.3.0",    // ScalaTags integration
  // Note: htmx4s-http4s is for http4s - we'll need ZIO HTTP equivalent
)
```

**HTMX strategy:**
- Primary interaction model for CMS frontend
- Server returns HTML fragments, not JSON
- Reduces JavaScript complexity significantly
- Aligns with OctoberCMS's original data-attributes philosophy

**Vue.js strategy:**
- Reserved for complex admin UI components (media manager, form builder)
- Mounts on specific DOM elements, not full SPA
- Communicates via JSON API endpoints
- Themes can declare Vue components for complex interactivity

**What NOT to use:**
- Alpine.js: WinterCMS's messy Snowboard+Alpine was explicitly called out as a problem. HTMX is simpler.
- React/Angular: Overkill for CMS, adds build complexity for theme developers.
- Full SPA mode: Server-rendered with progressive enhancement is better for SEO and initial load.

---

### Configuration & Serialization

| Technology | Version | Purpose | Rationale |
|------------|---------|---------|-----------|
| ZIO Config | 4.0.5 | Configuration loading | YAML/HOCON support, type-safe config derivation |
| ZIO Schema | 1.7.5 | Schema derivation | JSON/Protobuf/Avro codecs, form field validation |
| ZIO JSON | 0.7.x | JSON serialization | Schema-based, high performance |

**Confidence:** HIGH - Verified via [ZIO Config docs](https://zio.dev/zio-config/), [ZIO Schema docs](https://zio.dev/zio-schema/)

**Why ZIO Schema is critical for CMF:**
- **YAML-driven forms:** Schema can describe form fields, validation rules
- **Automatic codec derivation:** Plugin data models get JSON APIs for free
- **Migration support:** Schema evolution for plugin updates

```scala
libraryDependencies ++= Seq(
  "dev.zio" %% "zio-config" % "4.0.5",
  "dev.zio" %% "zio-config-yaml" % "4.0.5",
  "dev.zio" %% "zio-config-magnolia" % "4.0.5",  // Derivation
  "dev.zio" %% "zio-schema" % "1.7.5",
  "dev.zio" %% "zio-schema-json" % "1.7.5",
  "dev.zio" %% "zio-json" % "0.7.45"
)
```

---

### Logging & Observability

| Technology | Version | Purpose | Rationale |
|------------|---------|---------|-----------|
| ZIO Logging | 2.5.3 | Structured logging | ZIO-native, SLF4J bridge for Java libraries |
| ZIO Metrics | (ZIO Core) | Metrics collection | Built into ZIO 2.1, no separate library needed |

**Confidence:** HIGH - Verified via [ZIO Logging releases](https://github.com/zio/zio-logging/releases)

```scala
libraryDependencies ++= Seq(
  "dev.zio" %% "zio-logging" % "2.5.3",
  "dev.zio" %% "zio-logging-slf4j2-bridge" % "2.5.3"  // For Java libs
)
```

---

### Testing

| Technology | Version | Purpose | Rationale |
|------------|---------|---------|-----------|
| ZIO Test | 2.1.24 | Core testing | Part of ZIO core, property-based testing, test containers |
| TestContainers | 0.41.x | Integration tests | PostgreSQL containers for database tests |

**Confidence:** HIGH - ZIO Test is part of ZIO Core

```scala
libraryDependencies ++= Seq(
  "dev.zio" %% "zio-test" % "2.1.24" % Test,
  "dev.zio" %% "zio-test-sbt" % "2.1.24" % Test,
  "com.dimafeng" %% "testcontainers-scala-postgresql" % "0.41.4" % Test
)
```

---

### Build & Tooling

| Technology | Version | Purpose | Rationale |
|------------|---------|---------|-----------|
| Mill | 1.0.0+ | Build tool | 3-7x faster than sbt, simpler mental model, better IDE support |
| Scala CLI | 1.x | Scripts & utilities | Quick prototyping, migration scripts |

**Confidence:** HIGH - Verified via [Mill 1.0.0 announcement](https://mill-build.org/blog/13-mill-build-tool-v1-0-0.html)

**Why Mill over sbt:**
- **Performance:** Native launcher starts in ~100ms, 3-7x faster builds
- **Simplicity:** Standard Scala OOP model, not sbt's task/setting matrix
- **IDE support:** Jump-to-definition works, easier debugging
- **Zero-install JVM:** Launcher can download required JDK
- **Module scaling:** Handles hundreds of modules without slowdown (critical for plugin ecosystem)

**sbt considered but rejected:**
- Larger ecosystem BUT complex mental model
- Plugin developers would need to understand sbt deeply
- Performance degrades with many subprojects (each plugin = subproject)

**Mill build structure for plugins:**
```scala
// build.mill
import mill._
import mill.scalalib._

object core extends ScalaModule {
  def scalaVersion = "3.3.7"
  // Core CMF
}

object plugins extends Module {
  object blog extends ScalaModule {
    def moduleDeps = Seq(core)
    // Blog plugin
  }
  object user extends ScalaModule {
    def moduleDeps = Seq(core)
    // User plugin
  }
}
```

---

### Deployment

| Technology | Version | Purpose | Rationale |
|------------|---------|---------|-----------|
| Besom | 0.5.0 | Pulumi Scala SDK | Pure Scala IaC, type-safe infrastructure |
| Docker | Latest | Containerization | Standard deployment format |
| GraalVM Native Image | Optional | Native binaries | CLI tools, faster startup for serverless |

**Confidence:** MEDIUM - Besom verified via [GitHub](https://github.com/VirtusLab/besom), production patterns need validation

**Why Besom for Pulumi:**
- Pure Scala 3, not Java SDK wrapper
- Type-safe infrastructure definitions
- Functional, lazy evaluation semantics
- Can share types with application code

```scala
// Besom dependency (via Scala CLI or Mill)
//> using dep org.virtuslab::besom-core:0.5.0
//> using dep org.virtuslab::besom-aws:6.0.0
```

**Docker strategy:**
- Primary deployment target
- Multi-stage builds: compile with Mill, run with JRE
- Consider distroless base images for security

**GraalVM Native Image:**
- For CLI tools (scaffolding, migrations)
- Faster cold starts
- NOT for main server (reflection in Quill, ZIO may have issues)

---

## Complete Dependency Overview

```scala
// build.mill - Mill build file
import mill._
import mill.scalalib._

trait SummerCMSModule extends ScalaModule {
  def scalaVersion = "3.3.7"

  override def ivyDeps = Agg(
    // ZIO Core
    ivy"dev.zio::zio:2.1.24",
    ivy"dev.zio::zio-streams:2.1.24",

    // HTTP
    ivy"dev.zio::zio-http:3.8.1",

    // Database
    ivy"io.getquill::quill-jdbc-zio:4.8.6",
    ivy"org.postgresql:postgresql:42.7.5",
    ivy"org.flywaydb:flyway-core:10.22.0",
    ivy"org.flywaydb:flyway-database-postgresql:10.22.0",

    // Template
    ivy"com.lihaoyi::scalatags:0.13.1",

    // HTMX
    ivy"com.github.eikek::htmx4s-constants:0.3.0",
    ivy"com.github.eikek::htmx4s-scalatags:0.3.0",

    // Config & Schema
    ivy"dev.zio::zio-config:4.0.5",
    ivy"dev.zio::zio-config-yaml:4.0.5",
    ivy"dev.zio::zio-config-magnolia:4.0.5",
    ivy"dev.zio::zio-schema:1.7.5",
    ivy"dev.zio::zio-schema-json:1.7.5",
    ivy"dev.zio::zio-json:0.7.45",

    // Logging
    ivy"dev.zio::zio-logging:2.5.3",
    ivy"dev.zio::zio-logging-slf4j2-bridge:2.5.3"
  )

  override def testIvyDeps = Agg(
    ivy"dev.zio::zio-test:2.1.24",
    ivy"dev.zio::zio-test-sbt:2.1.24"
  )
}
```

---

## What NOT to Use

### Deprecated/Abandoned Libraries

| Library | Status | Use Instead |
|---------|--------|-------------|
| ZIO SQL | Deprecated | Quill |
| ZIO JDBC | Deprecated | Quill |
| Akka HTTP | License changed | ZIO HTTP |
| Slick | Lightbend ecosystem | Quill |

### Wrong Ecosystem

| Library | Issue | Use Instead |
|---------|-------|-------------|
| http4s | Cats Effect-native | ZIO HTTP |
| Doobie | Cats Effect-native | Quill |
| Circe | Cats-based JSON | ZIO JSON |
| fs2 | Cats Effect streams | ZIO Streams |
| Cats Effect | Different effect system | ZIO |

### Overkill for CMF

| Library | Issue | Use Instead |
|---------|-------|-------------|
| Play Framework | Too opinionated, heavyweight | ZIO HTTP + custom routing |
| Spring Boot | Java-centric, not idiomatic Scala | ZIO ecosystem |
| Tapir | Adds abstraction layer we don't need | ZIO HTTP declarative endpoints |

### Frontend Anti-Patterns

| Approach | Issue | Use Instead |
|----------|-------|-------------|
| Full SPA | SEO problems, complex build | HTMX + progressive enhancement |
| Alpine.js | WinterCMS's messy pattern | HTMX for simple, Vue for complex |
| Snowboard.js | WinterCMS-specific, deprecated | HTMX |

---

## Confidence Levels Summary

| Area | Level | Notes |
|------|-------|-------|
| ZIO Core (2.1.24) | HIGH | Production-proven, official releases verified |
| ZIO HTTP (3.8.1) | HIGH | Stable 3.x line, verified Feb 2025 release |
| Quill (4.8.6) | HIGH | Endorsed as only maintained ZIO RDBMS library |
| ScalaTags (0.13.1) | HIGH | Stable, well-maintained by Li Haoyi |
| htmx4s (0.3.0) | MEDIUM | Small but functional library, may need custom ZIO HTTP integration |
| Mill (1.0.0) | HIGH | Just hit 1.0, production-ready |
| Besom (0.5.0) | MEDIUM | Pre-1.0 but stable-candidate, VirtusLab maintained |
| Template strategy | MEDIUM | ScalaTags + Twirl hybrid needs validation with theme developers |

---

## Open Questions

### Requires Further Investigation

1. **Twirl vs custom template language:** Should we support Twig syntax for WinterCMS theme migration?

2. **htmx4s ZIO HTTP integration:** htmx4s has http4s module but not ZIO HTTP. Need to build adapter or use constants-only module.

3. **Plugin hot-reload:** Can Mill's watch mode + ZIO HTTP dev mode enable WinterCMS-like plugin hot-reload?

4. **WebSocket scaling:** Project context mentions "websockets scale poorly." ZIO HTTP has WebSocket support - research SSE as alternative for real-time features.

5. **GraalVM native compatibility:** Full server as native image may have issues with Quill/ZIO reflection. Validate if important for deployment.

6. **Datastar SDK:** ZIO HTTP 3.6+ includes Datastar SDK - evaluate as HTMX alternative for even simpler frontend patterns.

### Architecture Decisions Pending

- Plugin dependency resolution algorithm (WinterCMS uses PHP Composer-like)
- Theme rendering pipeline (compile-time vs runtime templates)
- Admin backend component system (Vue vs HTMX vs hybrid)

---

## Sources

### Official Documentation
- [ZIO HTTP Documentation](https://zio.dev/zio-http/)
- [ZIO Quill Getting Started](https://zio.dev/zio-quill/getting-started/)
- [ZIO Schema Documentation](https://zio.dev/zio-schema/)
- [ZIO Config Documentation](https://zio.dev/zio-config/)
- [Mill Build Tool](https://mill-build.org/mill/index.html)
- [Besom Pulumi Scala SDK](https://virtuslab.github.io/besom/)
- [ScalaTags Documentation](https://com-lihaoyi.github.io/scalatags/)

### Release Pages
- [ZIO Releases](https://github.com/zio/zio/releases) - v2.1.24
- [ZIO HTTP Releases](https://github.com/zio/zio-http/releases) - v3.8.1
- [Scala All Versions](https://www.scala-lang.org/download/all.html) - 3.3.7 LTS

### Strategy & Roadmap
- [Ziverge: ZIO in 2025](https://www.ziverge.com/post/zio-in-2025) - Ecosystem direction
- [Mill 1.0.0 Release](https://mill-build.org/blog/13-mill-build-tool-v1-0-0.html)

### Integration Examples
- [Rock the JVM ScalaTags + HTMX Demo](https://github.com/rockthejvm/scalatags-htmx-demo)
- [htmx4s GitHub](https://github.com/eikek/htmx4s)
- [ZIO Flyway DB Migrator](https://github.com/DenisNovac/zio-flyway-db-migrator)

---

*Stack research completed: 2026-02-04*
