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

4.1 KiB

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 (how it's built and consumed) and 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 §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

./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.
  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, the README module table, and (if status-worthy) 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.