davidtio 6692d5a053 refactor: migrate from Java HttpServer to Thorium framework
Replace com.sun.net.httpserver routing with Thorium's Server/Action/annotation
pattern. TaskController now owns @Get/@Post routes, form binding via data-mapping,
and the renderPage()/esc() helpers moved from Main. Main reduced to a 9-line
Thorium server entry point.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-28 23:31:18 +08:00

demoapp — Clouderized Demo App

A task manager built with Scala 3 + Thorium, used to demonstrate Clouderized's core value prop: stateful app upgrades with zero data loss.

Tasks are persisted in SQLite backed by a Docker named volume (demouser-data). Rebuilding or upgrading the container leaves all user data intact.

Prerequisites

  • Access to git.clouderized.com (Gitea)
  • The app deployed at demouser.clouderized.com
  • VPS SSH access: ssh -i ssh/id_rsa -p 9876 cldrzd@194.233.75.123

v1 → v2 Upgrade Demo (with data persistence)

This is the primary demo sequence. It shows that Clouderized can upgrade a running app without wiping user data.

1. Deploy v1.0.0

On the VPS:

cd ~/customers/demouser/demoapp && git fetch --tags && git checkout v1.0.0
cd ~/customers/demouser && docker compose up -d --build

Visit https://demouser.clouderized.com:

  • Teal header, version badge shows v1.0.0
  • Three pre-seeded tasks are present
  • /health returns {"status":"ok"}

2. Add user data

In the browser, add 23 tasks and delete one of the pre-seeded tasks. This simulates real user activity before an upgrade.

3. Upgrade to v2.0.0

On the VPS:

cd ~/customers/demouser/demoapp && git checkout v2.0.0
cd ~/customers/demouser && docker compose up -d --build

Revisit https://demouser.clouderized.com:

  • Blue header, version badge shows v2.0.0
  • All tasks added in step 2 are still there
  • Pre-seeded tasks are not re-added (seeding is skipped when the table is non-empty)

4. Verify persistence

# On the VPS — confirm the volume exists and is mounted
docker volume inspect demouser-data

How Persistence Works

Component Detail
Storage SQLite at /data/tasks.db inside the container
Volume Docker named volume demouser-data mounted at /data
Env var DB_PATH=/data/tasks.db (set in docker-compose.yml)
Seeding Pre-seed runs only when the tasks table is empty

The named volume demouser-data survives docker compose up --build — data is never lost on rebuild.


Config Reference

All visual changes are driven by src/main/resources/site.conf:

Key v1.0.0 v2.0.0 What it controls
app.version "1.0.0" "2.0.0" Version badge in header
app.theme.background "#0F766E" (teal) "#1D4ED8" (blue) Header and button color

Endpoints

Method Path Description
GET / Task list (HTML)
GET /health Health check (JSON)
POST /tasks Create task (form)
POST /tasks/:id/toggle Toggle completion
POST /tasks/:id/delete Delete task

Notes

  • The app runs on the Pro tier (2GB RAM, 2 vCPU) since JVM needs the headroom.
  • Local dev uses ./tasks.db (relative path) when DB_PATH is not set.
Description
Clouderized demo app — Scala/Thorium task manager
Readme 53 KiB
Languages
Scala 90.5%
Dockerfile 9.5%