Files
floret-kit/CONTRIBUTING.md
T
Jean-Luc Makiolaandmakiolaj 8b33635a85 Converge sibling branches into main (0.7.0) (#11)
Brings the branches the sibling apps actually ship from back onto main, so floret-kit stops forking per project.

Merged in:
- `vouch/settings` (what vouch pins), which already contains `feat/clockula` (what clockula pins) and `chore/deps-2026-10`: core-prefs, core-di, CollapsingScaffold FAB/no-back slots, the glance module, LocaleManager on API 33+, and the dependency bump
- `feat/glance-module`: the three glance commits clockula's branch didn't have yet (progress ring/tile/check button, expressive shapes + header pill, WidgetDoneState)

Both merged without conflicts. Version ends up at 0.7.0 (untagged).

Heads-up for consumers: the deps bump moves the toolchain to Gradle 9.8.0 / AGP 9.4.1 / Kotlin 2.4.20. Since floret-kit is a composite build, a consumer must be on Gradle >= 9.6 to pin anything from here on. Calendula builds, tests and lints against this branch with just that toolchain bump, no source changes.

Co-authored-by: Jean-Luc Makiola <business@jeanlucmakiola.de>
Reviewed-on: https://codeberg.org/jlmakiola/floret-kit/pulls/11
2026-10-07 09:36:15 +02:00

84 lines
4.1 KiB
Markdown

# 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 :core-prefs:testDebugUnitTest
./gradlew :core-di:test
./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 `:<module>` and add `include(":<module>")` to
[`settings.gradle.kts`](settings.gradle.kts).
2. Add a `<module>/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.<area>"`, `compileSdk 37` / `minSdk 29`, `jvmTarget = JVM_17`. An Android module with no
composables in it (e.g. `core-prefs`) applies only `android.library`.
- **Needs an annotation processor?** Add `alias(libs.plugins.ksp)` and declare
the processor with `ksp(...)` — see `core-di`, whose Hilt `@Module` has to be
processed in the library for a consuming app's component to see it.
3. Put sources under `src/main/kotlin/de/jeanlucmakiola/floret/<area>/`. 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 <kit-url> floret-kit`.
2. `includeBuild("floret-kit")` in the app's `settings.gradle.kts`.
3. `implementation("de.jeanlucmakiola.floret:<module>")` 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('<workflow>.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.