diff --git a/main/assets/js/search-data.json b/main/assets/js/search-data.json index f500eb0341..113848d68c 100644 --- a/main/assets/js/search-data.json +++ b/main/assets/js/search-data.json @@ -1303,7 +1303,7 @@ },"186": { "doc": "Codebase", "title": "Build System", - "content": "Gradle Kotlin DSL . All build files use Kotlin DSL (.gradle.kts). Configuration: . | Version catalog: gradle/libs.versions.toml | Convention plugins: build-logic/convention/ | Settings: settings.gradle.kts | . Convention Plugins . Located in build-logic/convention/src/main/kotlin/. The full set is registered in build-logic/convention/build.gradle.kts; these are the ones a module build applies most often: . | Plugin | Purpose | . | meshtastic.kmp.feature | Standard feature module setup | . | meshtastic.kmp.library | Shared KMP library module | . | meshtastic.kmp.library.compose | KMP library that also ships Compose UI | . | meshtastic.kmp.jvm.android | Adds the jvmAndroidMain source set shared by the Android and desktop JVM targets | . | meshtastic.koin | Koin Annotations + K2 compiler plugin | . | meshtastic.kotlinx.serialization | Serialization plugin setup | . | meshtastic.android.room | Room KMP setup and schema location | . | meshtastic.android.screenshot | Compose Preview screenshot testing | . The rest cover the application and library variants, lint, detekt, spotless, Dokka, Kover, AboutLibraries, analytics, secrets, the docs tasks and the root aggregate — read the register(…) block rather than assuming a plugin does or does not exist. Build Variants (Android) . | Flavor | Description | . | google | Google Play distribution; includes proprietary APIs | . | fdroid | F-Droid distribution; FOSS-only dependencies | . Key Gradle Tasks . # Compile check of every KMP module for JVM and iosSimulatorArm64 (excludes :desktopApp) ./gradlew kmpSmokeCompile # Run all tests: allTests covers KMP modules, test covers Android/JVM-only modules; run both ./gradlew test allTests # Code quality ./gradlew spotlessCheck detekt # Android build ./gradlew assembleGoogleDebug assembleFdroidDebug # Desktop run ./gradlew :desktopApp:run # Desktop native installers for the current OS (DMG / MSI+EXE / DEB+RPM+AppImage) ./gradlew :desktopApp:packageReleaseDistributionForCurrentOS # API reference (Dokka HTML → build/dokka/html) ./gradlew :dokkaGeneratePublicationHtml . ", + "content": "Gradle Kotlin DSL . All build files use Kotlin DSL (.gradle.kts). Configuration: . | Version catalog: gradle/libs.versions.toml | Convention plugins: build-logic/convention/ | Settings: settings.gradle.kts | . Convention Plugins . Located in build-logic/convention/src/main/kotlin/. The full set is registered in build-logic/convention/build.gradle.kts; these are the ones a module build applies most often: . | Plugin | Purpose | . | meshtastic.kmp.feature | Standard feature module setup | . | meshtastic.kmp.library | Shared KMP library module | . | meshtastic.kmp.library.compose | KMP library that also ships Compose UI | . | meshtastic.kmp.jvm.android | Adds the jvmAndroidMain source set shared by the Android and desktop JVM targets | . | meshtastic.koin | Koin Annotations + K2 compiler plugin | . | meshtastic.kotlinx.serialization | Serialization plugin setup | . | meshtastic.android.room | Room KMP setup and schema location | . | meshtastic.android.screenshot | Compose Preview screenshot testing | . The rest cover the application and library variants, lint, detekt, spotless, Dokka, Kover, AboutLibraries, analytics, secrets, the docs tasks and the root aggregate — read the register(…) block rather than assuming a plugin does or does not exist. Build Variants (Android) . | Flavor | Description | . | google | Google Play distribution; includes proprietary APIs | . | fdroid | F-Droid distribution; FOSS-only dependencies | . Key Gradle Tasks . # Compile check of every KMP module for JVM and iosSimulatorArm64 (excludes :desktopApp) ./gradlew kmpSmokeCompile # Run all tests: allTests covers KMP modules, test covers Android/JVM-only modules; run both ./gradlew test allTests # Code quality ./gradlew spotlessCheck detekt detektTypeResolved # Android build ./gradlew assembleGoogleDebug assembleFdroidDebug # Desktop run ./gradlew :desktopApp:run # Desktop native installers for the current OS (DMG / MSI+EXE / DEB+RPM+AppImage) ./gradlew :desktopApp:packageReleaseDistributionForCurrentOS # API reference (Dokka HTML → build/dokka/html) ./gradlew :dokkaGeneratePublicationHtml . ", "url": "/Meshtastic-Android/main/en/developer/codebase.html#build-system", "relUrl": "/en/developer/codebase.html#build-system" @@ -3627,7 +3627,7 @@ },"518": { "doc": "Contributing", "title": "Development Workflow", - "content": ". | Fork the repository (external contributors) or create a branch (maintainers). | Implement your changes following the architecture guidelines. | Test locally: ./gradlew spotlessCheck detekt kmpSmokeCompile test allTests | Commit with clear, descriptive messages. | Push and open a Pull Request. | . ", + "content": ". | Fork the repository (external contributors) or create a branch (maintainers). | Implement your changes following the architecture guidelines. | Test locally: ./gradlew spotlessCheck detekt detektTypeResolved kmpSmokeCompile test allTests | Commit with clear, descriptive messages. | Push and open a Pull Request. | . ", "url": "/Meshtastic-Android/main/en/developer/contributing.html#development-workflow", "relUrl": "/en/developer/contributing.html#development-workflow" @@ -3641,7 +3641,7 @@ },"520": { "doc": "Contributing", "title": "Pull Request Checklist", - "content": "Before submitting: . | Code compiles on all targets: ./gradlew kmpSmokeCompile | All tests pass: ./gradlew allTests | Code style passes: ./gradlew spotlessCheck | Static analysis passes: ./gradlew detekt | New code has appropriate test coverage | No android.* imports in commonMain | Koin modules registered if new DI is added | Routes added to Routes.kt if new navigation is introduced | Documentation updated if user-facing behavior changes | . ", + "content": "Before submitting: . | Code compiles on all targets: ./gradlew kmpSmokeCompile | All tests pass: ./gradlew allTests | Code style passes: ./gradlew spotlessCheck | Static analysis passes: ./gradlew detekt detektTypeResolved | New code has appropriate test coverage | No android.* imports in commonMain | Koin modules registered if new DI is added | Routes added to Routes.kt if new navigation is introduced | Documentation updated if user-facing behavior changes | . ", "url": "/Meshtastic-Android/main/en/developer/contributing.html#pull-request-checklist", "relUrl": "/en/developer/contributing.html#pull-request-checklist" @@ -3662,7 +3662,7 @@ },"523": { "doc": "Contributing", "title": "Verification", - "content": "Full pre-merge verification: ./gradlew spotlessCheck detekt kmpSmokeCompile test allTests . For docs-specific changes, also run: ./gradlew generateDocsBundle validateDocsBundle . Prose in docs/en/ follows Section 11 of the Meshtastic Client Design Standards — see Documentation Style for what’s specific to this repository. ", + "content": "Full pre-merge verification: ./gradlew spotlessCheck detekt detektTypeResolved kmpSmokeCompile test allTests . For docs-specific changes, also run: ./gradlew generateDocsBundle validateDocsBundle . Prose in docs/en/ follows Section 11 of the Meshtastic Client Design Standards — see Documentation Style for what’s specific to this repository. ", "url": "/Meshtastic-Android/main/en/developer/contributing.html#verification", "relUrl": "/en/developer/contributing.html#verification" @@ -7988,7 +7988,7 @@ },"1141": { "doc": "Developer Guide", "title": "Before You Open a PR", - "content": "Things that trip up first-time contributors — check these before requesting review: . | Formatting passes — run ./gradlew spotlessApply to auto-format, then verify with spotlessCheck | Detekt passes — run ./gradlew detekt and fix all reported issues | All tests pass — run ./gradlew test allTests (both are needed: test covers Android-only modules, allTests covers KMP) | Screenshot tests pass — if you touched any Compose UI, run ./gradlew :screenshot-tests:validateDebugScreenshotTest and update reference images if needed | Protos are an external dependency — protobuf models come from the org.meshtastic:protobufs Maven artifact (pinned in gradle/libs.versions.toml); change protos upstream and bump the version, never edit generated code locally | Docs updated — if you changed user-visible UI, update the corresponding page under docs/en/user/ | Previews updated — if you changed UI composables, update the corresponding *Previews.kt file and the screenshot-test baselines | Branch naming — branches must start with feat/, fix/, chore/, docs/, build/, ci/, refactor/, test/, or deps/ | . ", + "content": "Things that trip up first-time contributors — check these before requesting review: . | Formatting passes — run ./gradlew spotlessApply to auto-format, then verify with spotlessCheck | Detekt passes — run ./gradlew detekt detektTypeResolved and fix all reported issues; the second task runs the rules that need the compile classpath | All tests pass — run ./gradlew test allTests (both are needed: test covers Android-only modules, allTests covers KMP) | Screenshot tests pass — if you touched any Compose UI, run ./gradlew :screenshot-tests:validateDebugScreenshotTest and update reference images if needed | Protos are an external dependency — protobuf models come from the org.meshtastic:protobufs Maven artifact (pinned in gradle/libs.versions.toml); change protos upstream and bump the version, never edit generated code locally | Docs updated — if you changed user-visible UI, update the corresponding page under docs/en/user/ | Previews updated — if you changed UI composables, update the corresponding *Previews.kt file and the screenshot-test baselines | Branch naming — branches must start with feat/, fix/, chore/, docs/, build/, ci/, refactor/, test/, or deps/ | . ", "url": "/Meshtastic-Android/main/en/developer.html#before-you-open-a-pr", "relUrl": "/en/developer.html#before-you-open-a-pr" @@ -42022,7 +42022,7 @@ },"6003": { "doc": "Testing", "title": "Running tests", - "content": "# All tests: allTests covers KMP modules, test covers Android/JVM-only modules; run both ./gradlew test allTests # Specific module ./gradlew :feature:docs:allTests # Code quality ./gradlew spotlessCheck detekt # Full verification ./gradlew spotlessCheck detekt kmpSmokeCompile test allTests . ", + "content": "# All tests: allTests covers KMP modules, test covers Android/JVM-only modules; run both ./gradlew test allTests # Specific module ./gradlew :feature:docs:allTests # Code quality ./gradlew spotlessCheck detekt detektTypeResolved # Full verification ./gradlew spotlessCheck detekt detektTypeResolved kmpSmokeCompile test allTests . ", "url": "/Meshtastic-Android/main/en/developer/testing.html#running-tests", "relUrl": "/en/developer/testing.html#running-tests" diff --git a/main/en/developer.html b/main/en/developer.html index 4c0de51fe9..45b81e8cc6 100644 --- a/main/en/developer.html +++ b/main/en/developer.html @@ -1 +1 @@ - Developer Guide | Meshtastic Android Skip to main content Link Menu Expand (external link) Document Search Copy Copied
Meshtastic Docs ↗

Developer Guide

Technical documentation for contributing to the Meshtastic Android and Desktop app.

Before You Open a PR

Things that trip up first-time contributors — check these before requesting review:

  • Formatting passes — run ./gradlew spotlessApply to auto-format, then verify with spotlessCheck
  • Detekt passes — run ./gradlew detekt and fix all reported issues
  • All tests pass — run ./gradlew test allTests (both are needed: test covers Android-only modules, allTests covers KMP)
  • Screenshot tests pass — if you touched any Compose UI, run ./gradlew :screenshot-tests:validateDebugScreenshotTest and update reference images if needed
  • Protos are an external dependency — protobuf models come from the org.meshtastic:protobufs Maven artifact (pinned in gradle/libs.versions.toml); change protos upstream and bump the version, never edit generated code locally
  • Docs updated — if you changed user-visible UI, update the corresponding page under docs/en/user/
  • Previews updated — if you changed UI composables, update the corresponding *Previews.kt file and the screenshot-test baselines
  • Branch naming — branches must start with feat/, fix/, chore/, docs/, build/, ci/, refactor/, test/, or deps/

What’s New for Developers

September 2026 — Navigation & Deep Links — Deep links route through Navigation 3’s UriDeepLinkMatcher instead of a hand-rolled when block, and patterns are anchored, so an unmodelled trailing path no longer opens the family root.

September 2026 — Measurement & Formatting — NumberFormatter.format follows the OS locale; formatInvariant is the fixed-dot one for payloads another system parses.

September 2026 — Documentation Style — Section 11 of the Meshtastic design standards is now the style guide for docs/en/; this page keeps only the repository mechanics, the in-app renderer’s admonition form, and the prose rules the standards leave open.

August 2026 — Documentation Style — New page: the house style guide for docs/en/ prose, with rule IDs, a project word list, and the reasoning behind each convention.

August 2026 — Map tile sources are one shared catalogue in feature/map (MapTileCatalogue, RasterTileSpec), so both flavors draw the same raster base maps and overlays from one definition.

August 2026 — Both maps draw an imported feature’s own icon and drape a KMZ GroundOverlay image at its LatLonBox (rotation included) — MapLibre via an ImageSource quad, Google via GroundOverlayOptions (#3786).

August 2026 — Offline map-pack downloads are gated on offlineMapsSupported, since the MapLibre offline API compiles on Desktop but silently downloads nothing there.

August 2026 — New module feature/map-maplibre: the F-Droid flavor and Desktop now render every map surface (main map, node track, traceroute, discovery, inline mini-map) through maplibre-compose from one multiplatform module, and osmdroid is gone. The shared rules both renderers must agree on live in feature/map policy classes.


Table of contents


+ Developer Guide | Meshtastic Android Skip to main content Link Menu Expand (external link) Document Search Copy Copied
Meshtastic Docs ↗

Developer Guide

Technical documentation for contributing to the Meshtastic Android and Desktop app.

Before You Open a PR

Things that trip up first-time contributors — check these before requesting review:

  • Formatting passes — run ./gradlew spotlessApply to auto-format, then verify with spotlessCheck
  • Detekt passes — run ./gradlew detekt detektTypeResolved and fix all reported issues; the second task runs the rules that need the compile classpath
  • All tests pass — run ./gradlew test allTests (both are needed: test covers Android-only modules, allTests covers KMP)
  • Screenshot tests pass — if you touched any Compose UI, run ./gradlew :screenshot-tests:validateDebugScreenshotTest and update reference images if needed
  • Protos are an external dependency — protobuf models come from the org.meshtastic:protobufs Maven artifact (pinned in gradle/libs.versions.toml); change protos upstream and bump the version, never edit generated code locally
  • Docs updated — if you changed user-visible UI, update the corresponding page under docs/en/user/
  • Previews updated — if you changed UI composables, update the corresponding *Previews.kt file and the screenshot-test baselines
  • Branch naming — branches must start with feat/, fix/, chore/, docs/, build/, ci/, refactor/, test/, or deps/

What’s New for Developers

September 2026 — Navigation & Deep Links — Deep links route through Navigation 3’s UriDeepLinkMatcher instead of a hand-rolled when block, and patterns are anchored, so an unmodelled trailing path no longer opens the family root.

September 2026 — Measurement & Formatting — NumberFormatter.format follows the OS locale; formatInvariant is the fixed-dot one for payloads another system parses.

September 2026 — Documentation Style — Section 11 of the Meshtastic design standards is now the style guide for docs/en/; this page keeps only the repository mechanics, the in-app renderer’s admonition form, and the prose rules the standards leave open.

August 2026 — Documentation Style — New page: the house style guide for docs/en/ prose, with rule IDs, a project word list, and the reasoning behind each convention.

August 2026 — Map tile sources are one shared catalogue in feature/map (MapTileCatalogue, RasterTileSpec), so both flavors draw the same raster base maps and overlays from one definition.

August 2026 — Both maps draw an imported feature’s own icon and drape a KMZ GroundOverlay image at its LatLonBox (rotation included) — MapLibre via an ImageSource quad, Google via GroundOverlayOptions (#3786).

August 2026 — Offline map-pack downloads are gated on offlineMapsSupported, since the MapLibre offline API compiles on Desktop but silently downloads nothing there.

August 2026 — New module feature/map-maplibre: the F-Droid flavor and Desktop now render every map surface (main map, node track, traceroute, discovery, inline mini-map) through maplibre-compose from one multiplatform module, and osmdroid is gone. The shared rules both renderers must agree on live in feature/map policy classes.


Table of contents


diff --git a/main/en/developer/codebase.html b/main/en/developer/codebase.html index afe9ba77a8..d21234b687 100644 --- a/main/en/developer/codebase.html +++ b/main/en/developer/codebase.html @@ -60,7 +60,7 @@ ./gradlew test allTests # Code quality -./gradlew spotlessCheck detekt +./gradlew spotlessCheck detekt detektTypeResolved # Android build ./gradlew assembleGoogleDebug assembleFdroidDebug diff --git a/main/en/developer/contributing.html b/main/en/developer/contributing.html index 1f093a0409..fe71650aef 100644 --- a/main/en/developer/contributing.html +++ b/main/en/developer/contributing.html @@ -1,8 +1,8 @@ - Contributing | Meshtastic Android Skip to main content Link Menu Expand (external link) Document Search Copy Copied
Meshtastic Docs ↗

Contributing

Guidelines for contributing to the Meshtastic Android/Desktop project (a KMP codebase that also compiles for iOS).

Branch Naming

Branches use conventional-commit style prefixes:

Prefix Use for
feat/<scope> New user-visible behavior
fix/<scope> Bug fixes
refactor/<scope> Code structure changes
chore/<scope> Tooling, deps, CI, cleanup
docs/<scope> Documentation only
build/<scope> Build system changes
ci/<scope> CI workflow changes
test/<scope> Test additions or fixes
deps/<scope> Dependency updates

Timestamp-based spec prefixes (YYYYMMDD-HHMMSS-feature-name, as created by /speckit.git.feature) are also valid for spec-driven work.

Examples:

  • feat/desktop-ble-transport
  • fix/bluetooth-reconnect
  • 20260601-074653-air-quality-telemetry

Development Workflow

  1. Fork the repository (external contributors) or create a branch (maintainers).
  2. Implement your changes following the architecture guidelines.
  3. Test locally: ./gradlew spotlessCheck detekt kmpSmokeCompile test allTests
  4. Commit with clear, descriptive messages.
  5. Push and open a Pull Request.

Commit Messages

Follow conventional commit style:

feat(docs): add in-app documentation browser
+            Contributing | Meshtastic Android                      Skip to main content   Link      Menu      Expand       (external link)    Document      Search       Copy       Copied        
Meshtastic Docs ↗

Contributing

Guidelines for contributing to the Meshtastic Android/Desktop project (a KMP codebase that also compiles for iOS).

Branch Naming

Branches use conventional-commit style prefixes:

Prefix Use for
feat/<scope> New user-visible behavior
fix/<scope> Bug fixes
refactor/<scope> Code structure changes
chore/<scope> Tooling, deps, CI, cleanup
docs/<scope> Documentation only
build/<scope> Build system changes
ci/<scope> CI workflow changes
test/<scope> Test additions or fixes
deps/<scope> Dependency updates

Timestamp-based spec prefixes (YYYYMMDD-HHMMSS-feature-name, as created by /speckit.git.feature) are also valid for spec-driven work.

Examples:

  • feat/desktop-ble-transport
  • fix/bluetooth-reconnect
  • 20260601-074653-air-quality-telemetry

Development Workflow

  1. Fork the repository (external contributors) or create a branch (maintainers).
  2. Implement your changes following the architecture guidelines.
  3. Test locally: ./gradlew spotlessCheck detekt detektTypeResolved kmpSmokeCompile test allTests
  4. Commit with clear, descriptive messages.
  5. Push and open a Pull Request.

Commit Messages

Follow conventional commit style:

feat(docs): add in-app documentation browser
 fix(ble): handle reconnection timeout
 refactor(navigation): migrate to typed routes
 test(search): add keyword ranking tests
-

Pull Request Checklist

Before submitting:

  • Code compiles on all targets: ./gradlew kmpSmokeCompile
  • All tests pass: ./gradlew allTests
  • Code style passes: ./gradlew spotlessCheck
  • Static analysis passes: ./gradlew detekt
  • New code has appropriate test coverage
  • No android.* imports in commonMain
  • Koin modules registered if new DI is added
  • Routes added to Routes.kt if new navigation is introduced
  • Documentation updated if user-facing behavior changes

Code Style

  • Formatting: Enforced by Spotless (KtLint rules)
  • Static analysis: Detekt with project-specific configuration
  • Imports: No wildcard imports; organized automatically by Spotless
  • Line length: 120 characters maximum

Run formatting:

./gradlew spotlessApply
-

Architecture Rules

  • Feature modules must not depend on other feature modules
  • commonMain must not contain android.*, java.io.*, or platform-specific imports
  • Prefer interface + DI over expect/actual for complex platform behaviors
  • All navigation routes must be @Serializable and defined in Routes.kt
  • Use Koin annotations (@Single, @Factory, @Module) for dependency injection

Verification

Full pre-merge verification:

./gradlew spotlessCheck detekt kmpSmokeCompile test allTests
+

Pull Request Checklist

Before submitting:

  • Code compiles on all targets: ./gradlew kmpSmokeCompile
  • All tests pass: ./gradlew allTests
  • Code style passes: ./gradlew spotlessCheck
  • Static analysis passes: ./gradlew detekt detektTypeResolved
  • New code has appropriate test coverage
  • No android.* imports in commonMain
  • Koin modules registered if new DI is added
  • Routes added to Routes.kt if new navigation is introduced
  • Documentation updated if user-facing behavior changes

Code Style

  • Formatting: Enforced by Spotless (KtLint rules)
  • Static analysis: Detekt with project-specific configuration
  • Imports: No wildcard imports; organized automatically by Spotless
  • Line length: 120 characters maximum

Run formatting:

./gradlew spotlessApply
+

Architecture Rules

  • Feature modules must not depend on other feature modules
  • commonMain must not contain android.*, java.io.*, or platform-specific imports
  • Prefer interface + DI over expect/actual for complex platform behaviors
  • All navigation routes must be @Serializable and defined in Routes.kt
  • Use Koin annotations (@Single, @Factory, @Module) for dependency injection

Verification

Full pre-merge verification:

./gradlew spotlessCheck detekt detektTypeResolved kmpSmokeCompile test allTests
 

For docs-specific changes, also run:

./gradlew generateDocsBundle validateDocsBundle
 

Prose in docs/en/ follows Section 11 of the Meshtastic Client Design Standards — see Documentation Style for what’s specific to this repository.

Getting Help

  • Meshtastic Discord — #app-development channel
  • GitHub Issues — for bug reports and feature requests
  • GitHub Discussions — for questions and ideas

diff --git a/main/en/developer/testing.html b/main/en/developer/testing.html index 38ac1a2247..40036e3f5c 100644 --- a/main/en/developer/testing.html +++ b/main/en/developer/testing.html @@ -27,8 +27,8 @@ adb pull /data/local/tmp/store-screenshots/fdroid/. fastlane/metadata/android/en ./gradlew :feature:docs:allTests # Code quality -./gradlew spotlessCheck detekt +./gradlew spotlessCheck detekt detektTypeResolved # Full verification -./gradlew spotlessCheck detekt kmpSmokeCompile test allTests +./gradlew spotlessCheck detekt detektTypeResolved kmpSmokeCompile test allTests

CI integration

Tests run automatically on:

  • Pull request creation/update
  • Push to main
  • Pre-release validation

Single-runner jobs in reusable-check.yml run on the pinned Ubuntu LTS x64 label with JDK 25 and Gradle caching. Two jobs use a matrix: test-shards splits into shard-core, shard-feature and shard-app, and build-desktop runs across macOS, Windows and Linux x64 and arm64, on the labels its own matrix lists. Flatpak verification is its own workflow, not a job here. The pinned Ubuntu LTS arm label and the container-backed ubuntu-slim runners carry the lightweight jobs. .skills/testing-ci/SKILL.md has the four-tier rule.