Files
Jakub Zych 3f1fc59d23 docs(01): create phase 1 foundation plans
Phase 01: Foundation
- 3 plans in 3 waves (sequential dependency)
- Plan 01: Mill build + ZIO HTTP server
- Plan 02: PostgreSQL + Quill + Flyway migrations
- Plan 03: Repository pattern + Pulumi/Besom deployment

Ready for execution
2026-02-04 17:21:15 +01:00

6.2 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, must_haves
phase plan type wave depends_on files_modified autonomous must_haves
01-foundation 01 execute 1
build.mill
src/Main.scala
src/config/AppConfig.scala
src/api/Routes.scala
src/api/HealthRoutes.scala
resources/application.conf
true
truths artifacts key_links
Developer can run `mill run` and server starts on port 8080
GET /health returns 200 with 'ok' body
Server reads configuration from application.conf
Environment variables override HOCON values
path provides contains
build.mill Mill build configuration with ZIO dependencies zio-http
path provides exports
src/Main.scala Application entry point extending ZIOAppDefault
Main
path provides exports
src/config/AppConfig.scala Configuration case classes
AppConfig
ServerConfig
DatabaseConfig
path provides exports
src/api/Routes.scala Route composition
Routes
path provides contains
src/api/HealthRoutes.scala Health check endpoint /health
path provides contains
resources/application.conf HOCON configuration with env overrides server.port
from to via pattern
src/Main.scala src/api/Routes.scala Server.serve(routes) Server.serve
from to via pattern
src/Main.scala resources/application.conf ConfigProvider.fromResourcePath ConfigProvider
Set up the Mill build system and create a working ZIO HTTP server with health endpoints and HOCON configuration.

Purpose: Establish the foundational build infrastructure and prove the ZIO HTTP stack works before adding database complexity. Output: Running HTTP server accessible at localhost:8080 with /health endpoint.

<execution_context> @/home/jin/.claude/get-shit-done/workflows/execute-plan.md @/home/jin/.claude/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/phases/01-foundation/01-CONTEXT.md @.planning/phases/01-foundation/01-RESEARCH.md Task 1: Create Mill build configuration build.mill Create Mill build file with Scala 3 and ZIO dependencies.

Use programmatic Mill config (build.mill not YAML) for assembly support:

  • Scala version: 3.3.4 (LTS, better library compatibility than 3.8.x)
  • Dependencies:
    • dev.zio::zio:2.1.14
    • dev.zio::zio-http:3.0.1 (stable release, not 3.8.x which is unreleased)
    • dev.zio::zio-config:4.0.2
    • dev.zio::zio-config-typesafe:4.0.2
    • dev.zio::zio-config-magnolia:4.0.2
    • io.getquill::quill-jdbc-zio:4.8.5
    • org.postgresql:postgresql:42.7.4
    • org.flywaydb:flyway-core:10.21.0
    • org.flywaydb:flyway-database-postgresql:10.21.0

Include assembly configuration for fat JAR with:

  • Service file merging for META-INF/services
  • Exclude signature files (*.SF, *.DSA, *.RSA)

Note: Research suggested newer versions but use stable releases that exist on Maven Central. Run mill resolve _ to verify Mill parses the build file correctly build.mill exists and Mill can parse all dependencies

Task 2: Create project structure and configuration src/config/AppConfig.scala resources/application.conf Create configuration infrastructure:
  1. src/config/AppConfig.scala:
  • Case class AppConfig with server and database nested configs
  • Case class ServerConfig(host: String, port: Int)
  • Case class DatabaseConfig(host: String, port: Int, database: String, user: String, password: String)
  • Use zio-config-magnolia for automatic derivation
  1. resources/application.conf (HOCON):
server {
  host = "0.0.0.0"
  host = ${?SERVER_HOST}
  port = 8080
  port = ${?SERVER_PORT}
}

database {
  host = "localhost"
  host = ${?DB_HOST}
  port = 5432
  port = ${?DB_PORT}
  database = "summercms"
  database = ${?DB_NAME}
  user = "summercms"
  user = ${?DB_USER}
  password = "summercms"
  password = ${?DB_PASSWORD}
}

Pattern: Environment variables override defaults using HOCON substitution syntax. Files exist at correct paths AppConfig case classes defined, application.conf has all database and server settings with env overrides

Task 3: Create HTTP routes and Main entry point src/api/HealthRoutes.scala src/api/Routes.scala src/Main.scala Create the HTTP layer:
  1. src/api/HealthRoutes.scala:
  • Object HealthRoutes with routes val returning Routes
  • GET /health -> Response.text("ok")
  • Keep simple for now; /ready endpoint added when database exists
  1. src/api/Routes.scala:
  • Object Routes that composes all route modules
  • For now, just re-exports HealthRoutes.routes
  • This is the composition point for future route modules
  1. src/Main.scala:
  • Object Main extends ZIOAppDefault
  • Override bootstrap to set ConfigProvider.fromResourcePath()
  • In run: Server.serve(Routes.routes).provide(Server.defaultWithPort(8080))
  • Print ASCII art banner on startup (SummerCMS with sun motif)

ASCII banner example:

    \\   |   //
     \\  |  //
   ___\\###//___
  /   SUMMER    \\
  \\    CMS     /
   \\__________/

  Starting on port 8080...
Run `mill run` and curl localhost:8080/health returns "ok" Server starts, /health returns 200 with "ok" body, banner displays 1. `mill resolve _` succeeds (build file valid) 2. `mill compile` succeeds (code compiles) 3. `mill run` starts server (process runs) 4. `curl http://localhost:8080/health` returns "ok" (endpoint works) 5. Server logs show startup banner

<success_criteria>

  • Mill build configuration exists with all ZIO dependencies
  • Server starts on port 8080 via mill run
  • GET /health returns 200 OK with "ok" body
  • Configuration loads from application.conf
  • ASCII SummerCMS banner displays on startup </success_criteria>
After completion, create `.planning/phases/01-foundation/01-01-SUMMARY.md`