Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions .claude/skills/lukeneedham-conventions/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
name: lukeneedham-conventions
description: Luke Needham's conventions for Android apps - project setup, debug keystore, CI workflows, architecture (single activity, Compose, Navigation 3, MVVM, Koin DI) and the shared `common` debug library. Use when starting an app, adding a feature, screen, dependency or CI change, or touching logging, crashes or debug pages.
---

<!-- Copied from LukeNeedham/ci-workflows (skills/lukeneedham-conventions). Do not edit here: change it
in that repo. -->

# Luke's app conventions

The full, current guides are in the public repo `LukeNeedham/ci-workflows` under `docs/`:
`new-app.md` (read first when starting an app), `setup.md` (CI workflows), `library.md` and
`using-the-library.md` (shared library), `consuming-apps.md` (which apps use it). If you can reach
GitHub, read the relevant page there; otherwise the rules below are enough.

## Keep this skill current
Before starting any work in an app, compare this folder with `skills/lukeneedham-conventions` on `main` of
`LukeNeedham/ci-workflows` (public). If it differs, copy the shared folder over this one and include that
in the PR for the work you were asked to do, saying so in the description. Never open a PR just for this.

## Project
- Kotlin only, Gradle Kotlin DSL, version catalog (`gradle/libs.versions.toml`), Gradle wrapper.
- Package `com.lukeneedham.<app>` for both `namespace` and `applicationId`. App module is `:app`.
- AGP 8.13.2, Kotlin 2.2.21, Gradle 8.14.3 (bump together); `compileSdk`/`targetSdk` 36; `minSdk` 23+; JDK 17.
- **Commit a debug keystore** at `app/debug.keystore` (alias `androiddebugkey`, password `android`) and
use it for the `debug` signing config, so CI builds can update each other.
- No Android SDK in the sandbox: you usually cannot compile locally. CI is the first build.

## CI
- Callers `trigger_on_pull_request.yml` and `delete_prereleases.yml` come from
`LukeNeedham/ci-workflows/examples/`; the logic is in the shared reusable workflows there.
- `apk-path` is `app/build/outputs/apk/debug/app-debug.apk`; `comment-header` is `<app>-app-link`.
- Debug mode always comes from `BuildConfig.DEBUG` (the build config field).
- Open a PR for completed work. When the APK build comment appears on the PR, paste the download link into the chat.

## Architecture
- Single activity (`ComponentActivity`), Jetpack Compose + Material 3, no XML, no fragments.
- Navigation 3 (`NavKey` destinations that are `@Serializable`, back stack owned by the app).
- MVVM with unidirectional data flow: a `ViewModel` exposes one immutable `UiState` `StateFlow`; composables
use `collectAsStateWithLifecycle()` and send events up as function calls; no logic in composables.
- Coroutines + Flow; `viewModelScope` for screen work. UI -> domain/data layers; no Android types in the lower layer.
- **Koin for dependency injection**: `module { }` with `singleOf` / `viewModelOf` / `factoryOf`, `startKoin`
in `Application.onCreate`, `koinViewModel()` in composables. Constructor injection; classes never call Koin.
- Unit tests for ViewModels and repositories (JUnit, `kotlinx-coroutines-test`).

## Shared library (`com.lukeneedham:common`)
- Repository `https://lukeneedham.github.io/ci-workflows/maven` (group `com.lukeneedham` only); version in `libs.versions.toml`.
- Call `DebugKit.init(DebugKitConfig(enabled = BuildConfig.DEBUG))` first thing in `Application.onCreate`.
- Wrap the UI in `ProvideDebugSettings`, place a `DebugButton`, add `DebugPage`, `LogsPage`, `CrashesPage` to navigation.
- Use `Logger.d/i/w/e`, never `Log` or `println`. Scale animation durations with `LocalAnimationSpeed.current.scale(ms)`.
- Apps with their own debug tools keep their own debug page, with a button that opens the library's `DebugPage`.

## Updating
"Update all consuming apps" means every app with a library tick in `docs/consuming-apps.md` of
`ci-workflows`: bump `common` in each, one PR per app. Whenever a project starts using workflows, the
library or this skill, add it to that list.
2 changes: 2 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,3 +214,5 @@ See [docs/Release.md](docs/Release.md) for the full F-Droid release checklist (c
- Any new bottom sheet must use the common `SheetLayout` (see "Bottom sheets" above).
- Keep landscape/portrait-specific UI in `component/landscape/` and `component/portrait/`
subpackages, mirroring the calendar feature's structure.

Before starting work, check that `.claude/skills/lukeneedham-conventions` matches `skills/lukeneedham-conventions` on `main` of `LukeNeedham/ci-workflows`; if not, copy it over and include that in this work's PR. See that repo's `docs/skill.md`.
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/deps.kt
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ object deps {

object common {
/** Shared logger, crash handler and debug pages: https://github.com/LukeNeedham/ci-workflows */
val library = "com.lukeneedham:common:0.4.0"
val library = "com.lukeneedham:common:0.5.0"
}

object coil {
Expand Down
Loading