The project uses feature-first grouping. Code that belongs to the same feature lives together regardless of what layer it is in. A developer working on fantasy mode should find everything they need inside the fantasy package without jumping across the codebase.

Adapters are the exception. They are shared infrastructure used by multiple features and do not belong to any single feature. They live in their own top-level package and are injected into whichever features need them.

The rule is simple: if it serves one feature, it lives in that feature. If it serves multiple features, it lives in adapters or domain.

Top Level Structure

com.zoltraak.gateway
  features/       One package per product feature
  adapters/       Shared infrastructure adapters only
  domain/         Enums, shared contracts, internal models
  config/         Spring configuration and bean definitions
  security/       JWT filter chain and auth utilities
  annotations/    Custom meta-annotations

Features

Each feature package contains everything that feature owns: its controller, its service or orchestrator, its request and response DTOs, and any internal models specific to that feature. Nothing inside a feature package is referenced by another feature directly. Cross-feature communication goes through a service interface.

features/
  fantasy/
    FantasyController.java
    FantasyOrchestrator.java
    FantasyRequest.java
    FantasyResponse.java
    FantasyPipelineContext.java
  proxy/
    ChatProxyController.java
    OllamaProxyService.java
    OllamaProxyChatRequest.java
    OllamaProxyGenerateRequest.java
    OllamaProxyTagsResponse.java
  code/
    CodeAssistController.java
    CodingAssistantService.java
    CodeAssistRequest.java
    CodeAssistResponse.java
  gpu/
    GpuController.java
    GpuLifecycleManager.java
    PodState.java
    RequestQueue.java
    QueuedRequest.java
  bot/
    BotController.java
    TelegramBotService.java
    IntentClassificationRequest.java
    IntentClassificationResult.java
  cost/
    CostController.java
    CostTracker.java
    CostSession.java
    CostLog.java
    CostSummaryResponse.java
  health/
    HealthController.java
    HealthService.java
    HealthResponse.java

Adapters

Adapters are concrete implementations of ports. Each adapter knows about one external system. They are not feature-specific. The GPU lifecycle manager, the fantasy orchestrator, and the proxy service all use the same Ollama adapter for example. Each adapter folder contains the port interface, the concrete adapter, and the integration models specific to that external system.

adapters/
  gpu/
    GpuProviderPort.java
    RunPodAdapter.java
    VastAiAdapter.java
    model/
      RunPodPodResponse.java
      VastAiManageRequest.java
      VastAiInstanceResponse.java
      VastAiInstanceWrapper.java
  ollama/
    OllamaPort.java
    OllamaAdapter.java
    model/
      OllamaGenerateRequest.java
      OllamaGenerateResponse.java
      OllamaChatRequest.java
      OllamaChatResponse.java
      OllamaMessage.java
      OllamaTagsResponse.java
      OllamaModel.java
  comfyui/
    ComfyUiPort.java
    ComfyUiAdapter.java
    model/
      ComfyUIPromptRequest.java
      ComfyUIPromptResponse.java
      ComfyUIHistoryEntry.java
  bot/
    BotPort.java
    TelegramAdapter.java
    model/
      TelegramUpdate.java
      TelegramMessage.java
      TelegramChat.java
      TelegramUser.java
      TelegramPhotoSize.java
      TelegramDocument.java

Domain

Domain contains only what is truly shared across the entire system. Enums, the universal response envelope, shared contracts, and internal models that are not owned by any single feature. If a class is only used by one feature it belongs in that feature, not here.

domain/
  enums/
    PodStatus.java
    GpuProvider.java
    FantasyStage.java
    GatewayErrorCode.java
    BotIntent.java
    ModelType.java
  shared/
    GatewayResponse.java
    GatewayError.java
    ResponseMeta.java
    ChatMessage.java
    PodConnectionDetails.java
  auth/
    ZoltraakClaims.java
    RequestContext.java

Config

Spring configuration classes and property binding classes. This package wires beans together and reads configuration into typed objects.

config/
  WebClientConfig.java
  SecurityConfig.java
  SchedulingConfig.java
  properties/
    ZoltraakProperties.java
    ProviderProperties.java
    OllamaProperties.java
    GpuProperties.java
    QueueProperties.java
    TelegramProperties.java

Security

JWT validation filter chain and utility class. These apply globally across all requests and do not belong to any feature.

security/
  JwtAuthFilter.java
  JwtUtil.java