Example applications built with Ecstasy for deployment on the XQIZ.IT hosting platform.
This is a Gradle composite build. All examples are built together from the repository root using the XTC Gradle plugin.
examples/
├── build.gradle.kts # Root build — declares all example modules
├── settings.gradle.kts # Composite build settings
├── gradle.properties # Shared build properties
├── gradle/
│ └── libs.versions.toml # Version catalog (XTC, Node.js versions)
├── build-logic/ # Convention plugins (webapp integration)
│
├── welcome/ # Web app with React frontend
│ ├── build.gradle.kts
│ ├── src/main/x/ # Ecstasy source modules
│ │ ├── welcome.x # Main @WebApp module
│ │ ├── welcomeDB.x # Database schema
│ │ ├── welcomeCLI.x # CLI tool
│ │ └── welcomeTest.x # Standalone DB console app (run via :welcome:runXtc)
│ └── webapp/ # React app (npm build)
│
├── banking/ # Bank stress test demo
│ ├── build.gradle.kts
│ ├── src/main/x/
│ │ ├── Bank.x # @Database module
│ │ └── BankStressTest.x # @WebApp stress test
│ ├── src/test/x/
│ │ └── BankTest.x # xunit tests
│ └── webapp/public/ # Static web content
│
├── counter/ # Authenticated counter app
│ ├── build.gradle.kts
│ ├── src/main/x/
│ │ ├── count.x # @WebApp module (uses webauth)
│ │ └── countDB.x # Database schema
│ └── webapp/public/ # Static web content
│
└── chess-game/ # Composite build — chess game with AI opponent
├── build.gradle.kts # Composite root (lifecycle aggregator)
├── settings.gradle.kts
├── app/ # :app subproject — produces chess.xtc
│ ├── build.gradle.kts
│ ├── src/main/x/ # chess.x + chess/{ai,api,config,core,services,utils,validation}/
│ ├── src/test/x/ # 16 xunit test modules
│ └── webapp/public/ # Static web content (HTML/JS client)
└── db/ # :db subproject — produces chessDB.xtc
├── build.gradle.kts
└── src/main/x/ # chessDB.x + chessDB/{base,factory,models,pieces,types}/
-
Java 21+ on your PATH — needed to bootstrap the Gradle wrapper (
./gradlew). The Gradle daemon itself is auto-provisioned as JDK 25 from per-platform URLs ingradle/gradle-daemon-jvm.properties(required because the XTC plugin publishes with JVM-version 25 variant metadata), and Gradle additionally auto-provisions the JDK 25 compile toolchain for Ecstasy sources via Foojay. You do not need to install JDK 25 manually. Install a bootstrap JDK via SDKMAN (sdk install java), Adoptium, or your system package manager.To bump the daemon JDK version (or change vendor), regenerate the URLs:
./gradlew updateDaemonJvm --jvm-version=<NN> [--jvm-vendor=ADOPTIUM]. The task uses Foojay to write fresh per-platform download URLs intogradle/gradle-daemon-jvm.properties. Commit the result. -
XDK — resolved automatically from Maven repositories
-
Node.js — only needed for the
welcomeexample (auto-downloaded by default)
Alternatively, if you have Docker installed, you don't need any of the above — see Building with Docker below.
Build all examples from the repository root:
./gradlew buildBuild a single example:
./gradlew :chess-game:buildInstall all compiled modules to a single directory:
./gradlew installDist
# Output: build/install/examples/lib/Most examples are @WebApp modules that require the
XQIZ.IT platform to run. The
welcomeTest module is a standalone console app that can be run directly:
./gradlew :welcome:runXtcAfter building, you can also run any module directly with xtc run:
./gradlew installDist
xtc run -L build/install/examples/lib welcomeTestThe XTC Gradle plugin's runXtc/testXtc tasks accept a --mode option
controlling how the XTC process is launched:
| Mode | Behaviour |
|---|---|
DIRECT |
In-process, shares Gradle's JVM (fastest, no fork). |
ATTACHED (default) |
Forked JVM, stdout/stderr inherited; Gradle waits for the process to exit. |
DETACHED |
Forked JVM in the background; Gradle returns immediately. The PID is logged; stdout/stderr are redirected to timestamped log files under build/xtc/run_stdout_*.log (and stderr equivalent). |
Example:
./gradlew :welcome:runXtc --mode=DETACHED
# → [plugin] Started detached process with PID: 12345
# Gradle exits; welcomeTest keeps running. Tail the log file under
# welcome/build/xtc/ to see its output, and `kill <PID>` to stop it.DETACHED is intended for run/test tasks only; it has no effect on compile tasks and disables interactive stdin (the child has no inherited terminal).
Run all tests:
./gradlew buildxunit tests run automatically as part of the build. Test failures fail the
build (configured in build-logic's xtc-conventions plugin):
banking/src/test/x/BankTest.x— bank database operations.chess-game/app/src/test/x/Chess*Test.x— 16 modules covering chess logic, board operations, AI, validation, and time control.
GitHub Actions runs ./gradlew build, ./gradlew installDist, and a
welcomeTest smoke run on every push and pull request. The Dockerfile is
also built in CI to catch context drift. See .github/workflows/ci.yml.
If you have the XDK installed and on your PATH, you can compile and run
individual examples directly with xtc build and xtc run:
# Chess game (db must be compiled first; chess.x depends on chessDB)
xtc build -o out chess-game/db/src/main/x/chessDB.x
xtc build -o out -L out -r chess-game/app/webapp chess-game/app/src/main/x/chess.x
# chess.examples.org is @WebApp — needs the XQIZ.IT platform to host
# Welcome (requires npm build in welcome/webapp/ first)
xtc build -o out -r welcome/webapp welcome/src/main/x/*.x
xtc run -L out welcomeTest # standalone DB console app
# welcome.examples.org / welcomeCLI.examples.org are @WebApp — need the XQIZ.IT platform
# Counter
xtc build -o out -r counter/webapp counter/src/main/x/*.x
# count.examples.org is @WebApp — needs the XQIZ.IT platform
# Banking
xtc build -o out -r banking/webapp banking/src/main/x/*.x
# BankStressTest is @WebApp — needs the XQIZ.IT platform@WebApp modules (chess, welcome, count, BankStressTest) cannot be
run via plain xtc run — they require the XQIZ.IT platform to host them.
welcomeTest is a standalone module ... { void run() {...} } and is the
only example currently runnable directly with xtc run.
The included Dockerfile is a multi-stage build that:
- Compiles all examples using
gradle:jdk25(with dependency layer caching) - Copies the XVM runtime from
ghcr.io/xtclang/xvm:latest - Runs
welcomeTestas a build-time verification - Produces a slim JRE image with compiled modules and the
xtcCLI
# Build the image (compiles all examples, runs welcomeTest to verify)
docker build -t xtc-examples .
# Run the welcomeTest (default entrypoint)
docker run --rm xtc-examples
# Run any module using xtc
docker run --rm xtc-examples run -L /opt/examples/lib welcomeTest
# Copy the compiled modules to your local machine
docker run --rm -v "$(pwd)/out:/out" --entrypoint cp xtc-examples -r /opt/examples/lib/. /out/
ls out/*.xtcIf you don't have Java or Gradle installed, you can build directly from source and get the compiled modules on your local filesystem in one command:
docker run --rm -v "$(pwd):/workspace" -w /workspace gradle:jdk25 gradle build installDist
ls build/install/examples/lib/*.xtcThe output lands in build/install/examples/lib/ on your host machine via the
volume mount — no JDK, Gradle, or Node.js installation required.
To compile individual examples without Gradle, use the official XDK Docker image:
# Build the chess game modules (db first, then app — app depends on db)
docker run --rm -v "$(pwd):/workspace" ghcr.io/xtclang/xvm:latest \
xtc build -o /workspace/out /workspace/chess-game/db/src/main/x/chessDB.x
docker run --rm -v "$(pwd):/workspace" ghcr.io/xtclang/xvm:latest \
xtc build -o /workspace/out -L /workspace/out \
-r /workspace/chess-game/app/webapp \
/workspace/chess-game/app/src/main/x/chess.x
# Interactive shell
docker run -it --rm -v "$(pwd):/workspace" ghcr.io/xtclang/xvm:latest bash
cd /workspace
xtc build -o out chess-game/db/src/main/x/chessDB.x
xtc build -o out -L out -r chess-game/app/webapp chess-game/app/src/main/x/chess.xA "hello world" web application with a React frontend. Demonstrates @WebApp,
database integration (oodb), static content serving, and a CLI management tool.
The welcomeTest module is a standalone console app that exercises the database
layer directly. It opens a jsondb connection to the welcomeDB schema, looks
up a guest entry in the counters map, increments it, and prints the visit count:
$ ./gradlew runXtc -PmoduleName=welcomeTest
Welcome! You are guest #test-guest, visit #1
$ ./gradlew runXtc -PmoduleName=welcomeTest
Welcome! You are guest #test-guest, visit #2
The counter persists across runs because jsondb stores the database as JSON
files on disk. The data lives under data/ at the repository root (gitignored),
with the transaction log in data/sys/txlog.json and the counter values in
data/counters/. Delete the data/ directory to reset the database.
A bank database with concurrent transaction stress testing. Demonstrates
@Database, DBMap, DBCounter, and web-based stress test visualization.
An authenticated web application using the webauth module. Demonstrates
login/logout, session management, and per-user persistent counters.
A chess game server with an AI opponent. Demonstrates a larger multi-module application with game logic, database persistence, and a web client interface.
To use local (unpublished) XDK builds, ensure they are installed to Maven Local:
# In your xvm/xdk checkout:
./gradlew publishLocal
# Then build examples against the local snapshot:
./gradlew buildThe XTC version is configured in gradle/libs.versions.toml.