Outerstellar Outerstellar
← All Projects

Outerstellar Platform

A full-stack Kotlin platform template — multi-module architecture with observability, security, type-safe configuration, a JTE web layer, and a Swing desktop client.

Outerstellar Platform

A multi-module Kotlin project template with HTTP4k web and Swing desktop frontends, jOOQ/JDBI persistence, OpenTelemetry tracing, Micrometer metrics, and RBAC security. Intended as a starting point for new applications rather than a framework to depend on.

View on GitHub

How is the platform structured?

Seven modules with explicit dependency boundaries:

Module Responsibility Dependencies
platform-core Domain models, service interfaces, business logic Kotlin stdlib
platform-persistence-jooq Type-safe SQL, Flyway migrations, Caffeine caching jOOQ, Flyway, Caffeine
platform-persistence-jdbi JDBI alternative to the jOOQ module JDBI 3, Flyway
platform-sync-client Shared DTOs and HTTP client for component sync HTTP4k client
platform-security Auth models, RBAC, permissions, multi-realm auth
platform-web HTTP4k server, JTE templates, HTMX HTTP4k, JTE
platform-desktop Swing MVVM desktop client FlatLaf, MigLayout

Module Dependencies

platform-core  ←──  platform-security
      ↑                    ↑
      │                    │
platform-persistence-*     │
      ↑                    │
      │                    │
platform-web  ─────────────┘
platform-desktop ──────────┘

platform-core has no framework dependencies. Domain logic is testable without a server or database.

What patterns does the platform use?

Transactional Outbox

Background tasks and sync events are written to an outbox table in the same transaction as the domain change, then processed asynchronously. Avoids distributed transactions.

Contract-First API

Routes defined via http4k-contract produce an OpenAPI spec that stays in sync with the code:

"/api/v1/projects" meta {
    summary = "List all projects"
    returning(Status.OK, projectListLens to listOf(sampleProject))
} bindContract GET to { _ -> Response(Status.OK).with(projectListLens of projects) }

Configuration

Hoplite maps YAML, environment variables, and system properties to data classes. Environment-specific overrides use APP_PROFILE:

data class DatabaseConfig(
    val url: String,
    val username: String,
    val password: String,
    val maxPoolSize: Int = 10
)
# application.yaml
database:
  url: jdbc:h2:file:./data/dev
  username: sa
  password: ""

# application-production.yaml
database:
  url: ${DB_URL}
  username: ${DB_USER}
  password: ${DB_PASSWORD}
  maxPoolSize: 25

Observability

  • OpenTelemetry distributed tracing with trace ID propagation
  • Micrometer metrics for HTTP requests, cache hit rates, query timing
  • Caffeine cache stats exported to Micrometer
  • SLF4J + Logback with MDC context

Security

RBAC with resource-level permissions:

SecurityRules.hasPermission(
    Permission("report", "export"),
    permissionResolver,
    next
)

Authentication is pluggable via AuthRealm implementations. The template includes session-based auth; LDAP, OAuth, or API key realms can be added by implementing the interface and registering in Koin.

Getting Started

Requirements: JDK 21+, Maven 3.9+, PostgreSQL (production) or H2 (development, default).

# Build
mvn clean install

# Run web app (dev profile, H2)
mvn -pl platform-web -Pruntime-dev compile exec:java

# Or:
./start-web.ps1

# Run desktop app
./start-swing.ps1

Adding a Route

  1. Define a ViewModel:
data class DashboardViewModel(
    val stats: DashboardStats,
    val navigationMenu: List<NavigationLink>
) : ViewModel {
    override fun template() = "dashboard"
}
  1. Create a .kte template:
@param model: DashboardViewModel
@template.layout.base(content = @`
    <h1>${model.stats.title}</h1>
`)
  1. Register in App.kt:
"/dashboard" bind GET to { req ->
    val stats = dashboardService.getStats()
    Response(Status.OK).body(renderer(DashboardViewModel(stats, nav)))
}

How is the platform tested?

Level Tool Scope
Unit MockK Business logic in platform-core
Integration JUnit 5 + real DB Persistence and service layer
Architecture ArchUnit Module boundary and dependency enforcement
End-to-end HTTP4k in-memory Full request/response through the web layer
Desktop Xvfb container Swing UI via -Ptest-desktop profile

ArchUnit tests enforce that platform-core never imports from platform-web and that persistence types don't leak into the domain.

Tech Stack

Language Kotlin 2.x, JDK 21
Web HTTP4k, JTE, HTMX
Persistence jOOQ or JDBI 3, Flyway
DI Koin
Config Hoplite
Observability OpenTelemetry, Micrometer
Caching Caffeine
Desktop Swing, FlatLaf, MigLayout
Build Maven, GraalVM Native Image

FAQ

What is the Outerstellar Platform?

The Outerstellar Platform is a multi-module Kotlin project template for building full-stack JVM applications. It includes an HTTP4k web frontend with JTE templates, jOOQ/JDBI persistence with Flyway migrations, OpenTelemetry tracing, Micrometer metrics, RBAC security, and a Swing desktop client.

Is this a framework or a template?

It is a project template — you fork it and build on it. It is not a runtime dependency you add to your project. The architecture is opinionated but all code is yours to modify.

What databases does it support?

PostgreSQL for production and H2 for development. The persistence layer uses jOOQ (type-safe SQL) or JDBI as an alternative, with Flyway for schema migrations.

Does it support GraalVM native image?

Yes. The build is configured for GraalVM Native Image compilation via Maven.

What Java version is required?

JDK 21 or later, with Kotlin 2.x.

License

Apache License 2.0