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:

ModuleResponsibilityDependencies
platform-coreDomain models, service interfaces, business logicKotlin stdlib
platform-persistence-jooqType-safe SQL, Flyway migrations, Caffeine cachingjOOQ, Flyway, Caffeine
platform-persistence-jdbiJDBI alternative to the jOOQ moduleJDBI 3, Flyway
platform-sync-clientShared DTOs and HTTP client for component syncHTTP4k client
platform-securityAuth models, RBAC, permissions, multi-realm auth
platform-webHTTP4k server, JTE templates, HTMXHTTP4k, JTE
platform-desktopSwing MVVM desktop clientFlatLaf, 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?

LevelToolScope
UnitMockKBusiness logic in platform-core
IntegrationJUnit 5 + real DBPersistence and service layer
ArchitectureArchUnitModule boundary and dependency enforcement
End-to-endHTTP4k in-memoryFull request/response through the web layer
DesktopXvfb containerSwing 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

LanguageKotlin 2.x, JDK 21
WebHTTP4k, JTE, HTMX
PersistencejOOQ or JDBI 3, Flyway
DIKoin
ConfigHoplite
ObservabilityOpenTelemetry, Micrometer
CachingCaffeine
DesktopSwing, FlatLaf, MigLayout
BuildMaven, 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