Skip to content
CAI
Software that uses CAICheck a score

playframework/twirl

62.2

Adequate · 28 September 2026

4.8k

lines of production code

Scala

with Java

2

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

This system is the Twirl template engine, a library for compiling and rendering HTML, XML, and JavaScript templates in Scala applications. It provides a core API and parser that support Scala 2.12, 2.13, and 3, along with build plugins for sbt, Gradle, and Maven to integrate template compilation into standard Java/Scala build workflows. The system also exposes a Java API for programmatic template compilation and includes utilities for safe string escaping and incremental build performance.

How it got here

2013–2014 — Scala 3 migration and parser rewrite

15 changes.

The project underwent a significant architectural overhaul to support Scala 3, replacing the legacy template parser and AST with a new recursive-descent implementation. This period involved migrating the build infrastructure to sbt 2.x and introducing a Gradle plugin, while simultaneously expanding comprehensive test suites to validate the new compiler and parser behaviors.

2016–2022 — Scala 3 support and Java API expansion

9 changes.

The Twirl template engine API was rewritten to support Scala 2.12, 2.13, and 3, introducing version-specific implementations and improved escaping. A new Java compiler API was added to enable programmatic template compilation from Java build tools, accompanied by comprehensive test coverage for Scala.js, Scala 2, and Scala 3 environments.

2023 — Maven and Gradle plugin support

7 changes.

This period focused on expanding build tool integration by introducing a new Maven plugin and rewriting the Gradle plugin from scratch to support modern features like incremental compilation and the Worker API. The work included adding comprehensive test coverage for Scala 3 compatibility and establishing reproducible build environments through Gradle wrapper configurations.

Features

Add Maven plugin for compiling Twirl templates

Introduces the \maven-twirl\ plugin, providing \TwirlCompileMojo\ and \TwirlTestCompileMojo\ to compile Twirl templates into Scala sources during the Maven build lifecycle. The plugin supports configurable source/output directories, inclusion/exclusion filters, template formats, custom imports, constructor annotations, and source encoding, with a test suite verifying the end-to-end compilation of main and test templates.

maven-twirl · high confidence

Added Gradle wrapper and configuration files

The gradle-twirl directory now includes the Gradle wrapper scripts (gradlew, gradlew.bat), a .gitattributes file to enforce correct line endings for cross-platform compatibility, and a .gitignore file to exclude Gradle cache and build directories. This allows users to build the project using the bundled Gradle version without requiring a pre-installed Gradle environment.

gradle-twirl · high confidence

Added internal IO utility object for file and stream operations

The parser module now includes a new private \TwirlIO\ object that provides internal utilities for reading files, streams, and URLs as strings or byte arrays, writing strings to files, and deleting directories recursively. This object handles character encoding via a configurable codec and ensures resources are closed quietly, supporting the parser's underlying file I/O needs without exposing these capabilities as public API.

parser/src/main · high confidence

New Java API for Twirl template compilation

Added a new Java entry point class, \play.japi.twirl.compiler.TwirlCompiler\, which exposes Twirl template compilation capabilities to Java-based build tools like Maven and Gradle. This API allows users to compile Twirl templates programmatically from Java code, handling source encoding, formatter types, additional imports, and constructor annotations, while automatically resolving the correct Scala version and default imports at runtime.

compiler/src/main · high confidence

Removals

Removal of legacy Scala template parser and AST nodes

The \ScalaTemplateParser\ class and the \TreeNodes\ object, which defined the abstract syntax tree structures for the Play2 template language, have been removed from the codebase. This eliminates the recursive descent parser implementation and its associated data models, indicating a shift away from this specific template parsing mechanism.

src/main · high confidence

Behavioural changes

Automated CI test script for Play Framework components

A new shell script, scripts/test-code.sh, has been added to automate the testing and local publishing of the Play Framework's core components (API, parser, compiler, Maven plugin) and the Gradle plugin. The script orchestrates sbt commands to run full test suites for JVM and JS artifacts, publishes local artifacts with specific Scala versions, and executes Gradle checks, ensuring that the compiler and plugins are tested against the configured Scala matrix before final plugin verification.

scripts · high confidence

Gradle plugin now supports incremental compilation and Gradle 7.1+

The Gradle plugin for Twirl templates has been refactored to support incremental compilation and compatibility with Gradle 7.1 and later. This change introduces a new internal architecture using Gradle's WorkAction API (TwirlCompileAction) to handle template compilation and deletion individually, enabling better build performance through incremental builds. It also adds support for configuring template imports, constructor annotations, source encoding, and formatter types via the TwirlSourceDirectorySet, while maintaining backward compatibility with older Gradle versions through a deprecated Gradle7-specific implementation.

gradle-twirl/src/main/java/play/twirl/gradle/internal · high confidence

New Gradle plugin for compiling Twirl templates

The Gradle plugin for Twirl template compilation has been rewritten from scratch to support modern Gradle features. The new \TwirlPlugin\ (ID \com.playframework.twirl\) introduces a \twirl\ extension for configuring the Scala version, and allows per-source-set customization of template formats, imports, constructor annotations, and source encoding. Compilation is now handled by the \TwirlCompile\ task, which leverages Gradle's Worker API with process isolation for better performance and stability, and supports incremental builds and the Gradle Build Cache. The plugin automatically registers generated Scala code with the appropriate source sets and ensures the Twirl compiler dependency is managed via a dedicated, non-consumable configuration.

gradle-twirl/src/main/java/play/twirl/gradle · high confidence

New parser and compiler architecture with Scala 3 support

The template engine has been rebuilt with a new recursive-descent parser (TwirlParser) and updated compiler (TwirlCompiler) that replace the legacy implementation. This change introduces native support for Scala 3, including specific syntax adjustments like the 'using' keyword for implicit parameters and handling of vararg splices. The new parser enforces stricter grammar rules, such as allowing imports, variables, and sub-templates within 'if'/'else' blocks, and provides more accurate source position mapping for error reporting. The compiler now generates code compatible with both Scala 2 and Scala 3, ensuring consistent behavior across versions.

repository · high confidence

SbtTwirl plugin refactored for Scala 3 and sbt 1.x compatibility

The sbt-twirl plugin source has been restructured to support Scala 3 and modern sbt versions. A new \SbtTwirlCompat\ object provides a \Def.uncached\ shim for Scala 2 (where it is missing) while remaining empty for Scala 3, ensuring consistent behavior across versions. The main \SbtTwirl\ plugin and \TemplateCompiler\ have been updated to use the \sbt.{given, \_}\ import syntax required by sbt 1.x, and the compiler now explicitly accepts a \scalaVersion\ parameter to generate correct code for both Scala 2 and Scala 3. Additionally, the plugin's package has moved from \play.twirl.sbt\ to \play.twirl.sbt\ (consistent with the new groupId \org.playframework.twirl\), and the template compilation logic now correctly handles the \inclusiveDot\ setting and source encoding configuration.

sbt-twirl/src/main · high confidence

Twirl API core rewritten for Scala 2.12, 2.13, and 3

The Twirl template engine API in \api/shared/src/main\ has been completely rewritten to support Scala 2.12, 2.13, and 3. This introduces version-specific implementations of \BaseScalaTemplate\, \TwirlHelperImports\, and \package.scala\ to leverage idiomatic features of each Scala version (e.g., \scala.jdk.CollectionConverters\ in 2.13/3 vs \scala.collection.JavaConverters\ in 2.12, and Scala 3 syntax). The core template rendering logic in \BaseScalaTemplate\ now uses a dedicated \$twirl\_\_format\ parameter to avoid variable name clashes, and the \StringInterpolation\ class provides \html\, \xml\, and \js\ interpolators. New helper imports include \TwirlRichDate\ for date formatting, \TwirlRichString\ for conditional rendering, and \TwirlFeatureImports\ for language features like \@defining\, \@using\, and truthiness checks. The \Template\ traits now support up to 22 parameters, and \Html\ escaping is implemented via a custom \StringEscapeUtils\ to prevent XSS.

api/shared/src/main · high confidence

Test coverage

Added Scala 2-specific test helper for Twirl compiler integration; Added Scala 3 test helper for Twirl template compilation; Added Scala.js compilation test suite for Twirl templates; Added compiler test suite and benchmarking tool; Added comprehensive parser test suite; Added functional and unit tests for the Twirl Gradle plugin; Added parser test resources for case expressions, imports, and else-if logic; Added scripted test for Twirl compilation with Scala 3; Added scripted test for compiling templates with sbt plugin; Added scripted test for template compilation; Added test coverage for Twirl API content equality, formatting, and string interpolation; Added test for Scala.js compilation; Added tests for TemplateMapping and TemplatePosition; Added tests for the Java Twirl compiler API; Expanded compiler test suite for Twirl template features; Removal of TemplateParserSpec and test template.

Dependencies

Build infrastructure migrated to sbt 2.x with updated tooling and Scala versions

The project's build system has been upgraded to sbt 2.x (specifically the 2.1.0 nightly build), replacing the previous sbt 1.x environment. This migration includes updating core plugins such as sbt-scalajs to 1.22.0, sbt-mima-plugin to 1.2.1, and sbt-header to 5.11.0, alongside adding sbt-maven-plugin 0.0.4. The build now targets Java 17 and supports Scala versions 2.12.21, 2.13.18, and 3.3.8, with specific compiler flags configured for cross-compilation and binary compatibility checks.

project · high confidence

Introduce Gradle wrapper for the Twirl plugin project

The project now includes a Gradle wrapper configuration (gradle-wrapper.properties) that pins the build tool to version 9.8.0 (all distribution). This ensures that all developers and CI environments use the same Gradle version, improving build reproducibility and removing the dependency on a globally installed Gradle.

gradle-twirl/gradle · high confidence

New Gradle plugin and build infrastructure for Twirl

This change introduces a new Gradle plugin for compiling Twirl templates, located in the \gradle-twirl\ directory. The plugin is configured via \build.gradle.kts\ and \gradle/libs.versions.toml\, utilizing Gradle Version Catalogs to manage dependencies such as Spotless 8.10.2, AssertJ 3.27.7, and Freemarker 2.3.35. It publishes under the ID \org.playframework.twirl\ and includes signing and Nexus publishing support. Additionally, the root \build.sbt\ has been significantly refactored to support Scala 3, cross-compilation for JVM and JS platforms, and binary compatibility checks via MiMa, while the \docs\ project now uses a separate \build.sbt\ to handle Play documentation generation.

(dependencies) · high confidence

Housekeeping

Project initialization and tooling configuration

The repository has been initialized with a new Apache 2.0 license, a comprehensive README documenting the Twirl template engine for both sbt and Maven, and a .gitignore file updated to exclude IDE and build artifacts. Additionally, the project is now configured with scalafmt version 3.11.5 for code formatting, and a .git-blame-ignore-revs file has been added to ignore automated reformatting commits.

(repo-wide) · high confidence

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.

Score

  • CAI 62 → 62 (+0.1)
  • Rubric changed (rubric-2026.09.8 → rubric-2026.09.16) — scores are not directly comparable.

Lenses

  • Code Health 92 → 92 (-0.1)
  • Architecture 100 → 92 (-8.5)
  • Maturity 54 → 54 (+0.3)
  • Readiness 74 → 77 (+2.7)
  • Security 55 → 55 (+0.0)

Resolved (13)

  • Documentation: no contributor guidance
  • Documentation: no installation or build instructions
  • Documentation: no licence statement
  • Documentation: no project overview
  • Documentation: no usage examples
  • Further sole-owners (lower concentration)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • Off-boarding risk: anonymized user #1

New (9)

  • Duplicated block (5 lines × 2) (gradle-twirl/src/main/java/play/twirl/gradle/internal/DefaultTwirlSourceDirectorySet.java)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • High: security finding (details withheld)
  • Off-boarding risk: anonymized user #1
  • Scanner failed to run — not a clean result

Changes since last survey

  • 45 commits — 43 feature/other, 2 fixes

By area

  • (repo) — 21 commits
  • (root) — 4 commits
  • gradle-twirl/gradle — 4 commits
  • .github/workflows — 3 commits
  • docs/build.sbt — 2 commits
  • docs/project — 2 commits
  • project/plugins.sbt — 2 commits
  • sbt-twirl/src — 2 commits
  • .github/scala-steward.conf — 1 commit
  • compiler/src — 1 commit
  • gradle-twirl/gradlew.bat — 1 commit
  • gradle-twirl/src — 1 commit
  • project/Dependencies.scala — 1 commit

Notable commits

  • fix: Revert "Use sbt nightly from (usually blocked) repo.scala-sbt.org to fix snapshots checksums"
  • fix: Use sbt nightly from (usually blocked) repo.scala-sbt.org to fix snapshots checksums
  • change: Allow to make use of sbt nightly from (usually blocked) repo.scala-sbt.org
  • change: Avoid deprecated Gradle APIs on Gradle 9
  • change: Build Scala 3 artifacts with 3.3 and test newer versions
  • change: Build with sbt 2.1.0-M1 and Scala 3.9.0
  • change: Bump com.diffplug.spotless from 8.10.0 to 8.10.2 in /gradle-twirl
  • change: Bump com.gradle.plugin-publish from 2.1.1 to 2.2.1 in /gradle-twirl
  • change: Bump gradle-wrapper from 9.4.1 to 9.7.1 in /gradle-twirl
  • change: Bump gradle-wrapper from 9.7.1 to 9.8.0 in /gradle-twirl
  • change: Centralize Scala versions in test builds
  • change: Empty - just triggering new sonatype snapshot
  • change: Latest sbt nightly
  • change: Merge pull request #1290 from playframework/dependabot/gradle/gradle-twirl/gradle-wrapper-9.7.1
  • change: Merge pull request #1295 from playframework/dependabot/gradle/gradle-twirl/org.freemarker-freemarker-2.3.35
  • change: Merge pull request #1299 from scala-steward/update/scala3-compiler-3.9.0
  • change: Merge pull request #1309 from scala-steward/update/patches
  • change: Merge pull request #1313 from playframework/dependabot/gradle/gradle-twirl/com.gradle.plugin-publish-2.2.1
  • change: Merge pull request #1314 from playframework/dependabot/gradle/gradle-twirl/com.diffplug.spotless-8.10.2
  • change: Merge pull request #1317 from mkurz/pin-scala-2.13.x-main
  • …and 25 more

Architecture

  • Containers 0 added · 0 removed · contexts 2 added · 1 removed · edges 0 added · 0 removed

Added bounded contexts (2)

  • docs
  • gradle-twirl

Removed bounded contexts (1)

  • simple

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

playframework/twirl was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 28 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit 25a73b0961357fd463107b3958556d480fb5ff05 — the exact code this score is about.
  • Scored under rubric-2026.09.16 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-d46da229e3fd.