# Kell Creations — Cross-Platform Shell Composition Strategy

## Overview

This document describes the shared composition pattern that all Kell Creations
app targets (`kell_web`, `kell_mobile`, future targets) must follow. The pattern
lives in the `core` package and provides a consistent way to:

1. Read runtime configuration from `--dart-define` values.
2. Construct environment-appropriate services (fake vs. real backends).
3. Expose services and configuration to the widget tree.

## Architecture

```
┌──────────────────────────────────────────────────────────────┐
│                     core (shared package)                     │
│                                                              │
│  KcAppConfig / KcAppEnvironment                              │
│    └─ Runtime config from --dart-define                      │
│                                                              │
│  KcAppServices (abstract)                                    │
│    └─ Base class for app service containers                  │
│                                                              │
│  KcServiceFactory<T extends KcAppServices>                   │
│    └─ Generic factory: createFake() / createWordPress(cfg)   │
│                                                              │
│  KcBootstrap                                                 │
│    └─ Shared bootstrap: env switch + WP credential fallback  │
│                                                              │
│  KcAppScope<T extends KcAppServices>                         │
│    └─ InheritedWidget exposing T + KcAppConfig to tree       │
└──────────────────────────────────────────────────────────────┘
         ▲                              ▲
         │                              │
┌────────┴───────────┐     ┌────────────┴──────────────┐
│    kell_web (app)   │     │    kell_mobile (app)       │
│                     │     │                            │
│  AppServices        │     │  MobileAppServices         │
│    extends          │     │    extends                 │
│    KcAppServices    │     │    KcAppServices           │
│                     │     │                            │
│  AppScope           │     │  (uses KcAppScope           │
│    extends          │     │   <MobileAppServices>)     │
│    KcAppScope       │     │                            │
│    <AppServices>    │     │                            │
│                     │     │                            │
│  Bootstrap          │     │  (uses KcBootstrap.run      │
│    delegates to     │     │   with own factory)        │
│    KcBootstrap.run  │     │                            │
└─────────────────────┘     └────────────────────────────┘
```

## Why abstract services?

Concrete service containers hold references to feature-package repository types
(e.g., `InventoryRepository`, `ProductPublishingRepository`). Moving those
references into `core` would create **circular dependencies**:

```
core → feature_wordpress → core  ← NOT ALLOWED
```

By keeping `KcAppServices` abstract in `core`, the package owns the composition
**contract** without knowing concrete types. Each app provides its own concrete
subclass.

## Contract for new app targets

When creating a new app target (e.g., `kell_mobile`), follow this pattern:

### 1. Create a concrete services class

```dart
// apps/kell_mobile/lib/composition/mobile_app_services.dart
import 'package:core/core.dart';
import 'package:feature_inventory/feature_inventory.dart';
import 'package:feature_wordpress/feature_wordpress.dart';
// ... other feature imports

class MobileAppServices extends KcAppServices {
  final InventoryRepository inventoryRepository;
  final ProductPublishingRepository productPublishingRepository;
  // ... other repositories as needed

  const MobileAppServices({
    required this.inventoryRepository,
    required this.productPublishingRepository,
  });

  factory MobileAppServices.fake() {
    return MobileAppServices(
      inventoryRepository: FakeInventoryRepository(),
      productPublishingRepository: FakeProductPublishingRepository(),
    );
  }

  factory MobileAppServices.wordpress({
    required String siteUrl,
    required String consumerKey,
    required String consumerSecret,
  }) {
    final apiClient = WooCommerceApiClient(
      siteUrl: siteUrl,
      consumerKey: consumerKey,
      consumerSecret: consumerSecret,
    );
    return MobileAppServices(
      inventoryRepository: FakeInventoryRepository(),
      productPublishingRepository:
          WordPressProductPublishingRepository(apiClient: apiClient),
    );
  }

  static KcServiceFactory<MobileAppServices> get serviceFactory {
    return KcServiceFactory<MobileAppServices>(
      createFake: () => MobileAppServices.fake(),
      createWordPress: (config) => MobileAppServices.wordpress(
        siteUrl: config.wcSiteUrl,
        consumerKey: config.wcConsumerKey,
        consumerSecret: config.wcConsumerSecret,
      ),
    );
  }
}
```

### 2. Wire up main.dart

```dart
// apps/kell_mobile/lib/main.dart
import 'package:core/core.dart';
import 'package:flutter/material.dart';

import 'composition/mobile_app_services.dart';

void main() {
  final config = KcAppConfig.fromEnvironment();
  final (:services, config: effectiveConfig) = KcBootstrap.run(
    config,
    MobileAppServices.serviceFactory,
  );

  runApp(
    KcAppScope<MobileAppServices>(
      services: services,
      config: effectiveConfig,
      child: const KellMobileApp(),
    ),
  );
}
```

### 3. Access services in widgets

```dart
// Anywhere in the widget tree:
final services = KcAppScope.of<MobileAppServices>(context);
final config = KcAppScope.configOf<MobileAppServices>(context);
```

## Backward compatibility (kell_web)

The `kell_web` app retains its original class names (`AppConfig`, `AppScope`,
`Bootstrap`, `AppServices`) as thin wrappers/typedefs around the shared `core`
types. Existing code continues to work without modification:

| Original (kell_web) | Shared (core)      | Relationship    |
| ------------------- | ------------------ | --------------- |
| `AppConfig`         | `KcAppConfig`      | typedef         |
| `AppEnvironment`    | `KcAppEnvironment` | typedef         |
| `AppServices`       | `KcAppServices`    | extends         |
| `AppScope`          | `KcAppScope`       | extends (typed) |
| `Bootstrap`         | `KcBootstrap`      | delegates       |

New code in `kell_web` may use either the original names or the shared `Kc`-prefixed
names. The shared names are preferred for clarity and consistency with `kell_mobile`.

## Runtime configuration

All app targets use the same `--dart-define` keys:

| Key                     | Description                          | Default |
| ----------------------- | ------------------------------------ | ------- |
| `KC_ENV`                | `fake` or `wordpress`                | `fake`  |
| `KC_WC_SITE_URL`        | WordPress site URL                   | (empty) |
| `KC_WC_CONSUMER_KEY`    | WooCommerce REST API consumer key    | (empty) |
| `KC_WC_CONSUMER_SECRET` | WooCommerce REST API consumer secret | (empty) |

When `KC_ENV=wordpress` but credentials are missing, `KcBootstrap` automatically
falls back to fake mode with a debug-mode warning.

## What remains app-specific

The following concerns are **not** shared and remain in each app target:

- **App shell / navigation** — Web uses `NavigationRail`, mobile will use
  `BottomNavigationBar` or similar.
- **Routing** — Route definitions and page builders are platform-specific.
- **Platform-specific presentation** — Layout, responsive breakpoints, etc.
- **Cross-feature navigation handoffs** — Wired in the app's routing layer.

The `design_system` package provides shared visual components (widgets, theme,
typography, breakpoints) that both web and mobile can use for consistent styling.
