# Contributing to floret-kit floret-kit is the shared Material 3 Expressive design system + plumbing for the Floret app family. Before changing it, skim [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) (how it's built and consumed) and [`docs/ROADMAP.md`](docs/ROADMAP.md) (what's in scope). This file is the practical how. ## The rules 1. **Share mechanics, not look.** Extract the machinery; leave seed colours, palettes, identity chips, and wording to the apps. If a piece can't be made app-agnostic without contortion, it doesn't belong here yet. 2. **No app coupling.** A kit module never imports an app package, an app's `R`, or a domain type. App-specific values arrive as **constructor/config parameters** or **callbacks** (see `core-crash`'s `CrashConfig`, `InlineTextField`'s `capitalization`). 3. **String resources are fallbacks.** Kit strings are English defaults an app overrides via resource merge. Don't put app-specific or per-app-divergent wording in the kit. 4. **Bake divergence into parameters, don't pick a silent winner.** Where two apps differ, expose the difference. When a shared primitive adopts one app's version as canonical, that's a deliberate, documented convergence. 5. **No `foojay` toolchain resolver** — not in any `*.gradle.kts`, not even as a token in a comment. It breaks reproducible / official F-Droid builds. Set `jvmTarget` directly. See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) §5. ## Prerequisites - JDK 17 - Android SDK (compileSdk 37) for the Android modules — set `ANDROID_HOME` or add a gitignored `local.properties` with `sdk.dir`. Pure-JVM modules need neither. ## Build & test ```sh ./gradlew :core-time:test # JVM module (JUnit 5 + Truth) ./gradlew :core-crash:testDebugUnitTest ./gradlew :identity:assembleDebug ./gradlew build # everything ``` In practice the kit is exercised through a consuming app's composite build (e.g. `agendula`'s `./gradlew assembleDebug`), which compiles the included modules from source. ## Adding a module 1. Create `:` and add `include(":")` to [`settings.gradle.kts`](settings.gradle.kts). 2. Add a `/build.gradle.kts`: - **JVM:** `plugins { alias(libs.plugins.kotlin.jvm) }`, a `kotlin { compilerOptions { jvmTarget = JVM_17 } }` block, JUnit 5 test deps. - **Android:** `plugins { alias(libs.plugins.android.library); alias(libs.plugins.kotlin.compose) }` (no `kotlin.android` — AGP 9.x is built-in), `namespace = "de.jeanlucmakiola.floret."`, `compileSdk 37` / `minSdk 29`, `jvmTarget = JVM_17`. 3. Put sources under `src/main/kotlin/de/jeanlucmakiola/floret//`. The root build's `subprojects {}` sets the shared `group`/`version`, so no per-module coordinates are needed. 4. Add an entry to [`CHANGELOG.md`](CHANGELOG.md), the README module table, and (if status-worthy) [`docs/ROADMAP.md`](docs/ROADMAP.md). ## Adopting the kit in an app 1. `git submodule add floret-kit`. 2. `includeBuild("floret-kit")` in the app's `settings.gradle.kts`. 3. `implementation("de.jeanlucmakiola.floret:")` in the app module. 4. Ensure CI checks out submodules (`submodules: recursive`) and the included build can find the SDK (`ANDROID_HOME`). For official F-Droid reproducible builds, add `submodules: true` to the fdroiddata recipe and have the repro guard scan the submodule. 5. The app pins a kit commit via the submodule; bump it deliberately to adopt kit changes. ## Validate before pushing - `python3 -c "import yaml; yaml.safe_load(open('.yml'))"` after any workflow edit — indentation bites. - A consuming app's `lintDebug` + `testDebugUnitTest` + `assembleDebug` should be green after a kit change you mean to land.