6.9 KiB
6.9 KiB
Amethyst Desktop Fork
Project Overview
Fork of Amethyst adding Compose Multiplatform Desktop support. Quartz library converted to full KMP for code sharing between Android and Desktop JVM.
Architecture
amethyst/
├── quartz/ # Nostr KMP library (protocol only, no UI)
│ └── src/
│ ├── commonMain/ # Shared Nostr protocol, data models
│ ├── androidMain/ # Android-specific (crypto, storage)
│ └── jvmMain/ # Desktop JVM-specific
├── commons/ # Shared UI components (convert to KMP)
│ └── src/
│ ├── commonMain/ # Shared composables, icons, state
│ ├── androidMain/ # Android-specific UI utilities
│ └── jvmMain/ # Desktop-specific UI utilities
├── desktopApp/ # Desktop JVM application (layouts, navigation)
├── amethyst/ # Android app (layouts, navigation)
└── ammolite/ # Support module
Sharing Philosophy:
quartz/= Business logic, protocol, data (no UI)commons/= Shared UI components, icons, composablesamethyst/&desktopApp/= Platform-native layouts and navigation
Tech Stack
| Layer | Technology |
|---|---|
| Core | Quartz (Nostr KMP) |
| UI | Compose Multiplatform 1.7.x |
| Async | kotlinx.coroutines + Flow |
| Network | OkHttp (JVM) |
| Serialization | Jackson |
| DI | Manual / Koin |
| Build | Gradle 8.x, Kotlin 2.1.0 |
Skills
Specialized skills provide domain expertise with bundled resources and patterns:
| Skill | Expertise | When to Use |
|---|---|---|
nostr-expert |
Nostr protocol (Quartz library) | Event types, NIPs, tags, signing, Bech32 |
kotlin-expert |
Advanced Kotlin patterns | StateFlow, sealed classes, @Immutable, DSLs |
kotlin-coroutines |
Advanced async patterns | supervisorScope, callbackFlow, relay pools, testing |
kotlin-multiplatform |
Platform abstraction | expect/actual, source sets, sharing decisions |
compose-expert |
Shared UI components | Material3, state hoisting, recomposition |
android-expert |
Android platform | Navigation, permissions, lifecycle, Material3 |
desktop-expert |
Desktop platform | Window, MenuBar, Tray, keyboard shortcuts |
gradle-expert |
Build system | Dependencies, versioning, packaging, optimization |
Workflow
When you ask for a feature:
- Quick skill assessment - I identify which skills are relevant
- Propose which skills - I present which skills I'll use for the task
- Get approval - You review and approve (or adjust) the skill selection
- Review plan using approved skills - I invoke the approved skills to create detailed implementation plan
- Execute with skills - Skills collaborate to implement the feature
Example:
You: "Add video support to notes"
Me: "I'll use:
- /nostr-expert (NIP-71 video events)
- /compose-expert (video player UI)
- /android-expert (platform video APIs)
Proceed?"
You: "yes"
Me: [invokes skills to create plan]
"Plan from skills:
1. nostr-expert: Use NIP-71 kind 34235 for video events...
2. compose-expert: Create VideoPlayer composable in commons...
3. android-expert: Use ExoPlayer for Android...
Proceed with implementation?"
You: "yes"
Me: [implements using skill guidance]
Commands
/desktop-run- Build and run desktop app/nip <number>- Get NIP implementation guidance
Feature Workflow
When picking up a new task or feature, follow this process:
Step 1: Analyze Android Implementation
Start by examining the existing Android Amethyst codebase:
- Find the relevant feature/component in
amethyst/module - Understand the current implementation patterns
- Identify dependencies and integrations
Step 2: Create Implementation Plan
Before coding, create a plan that categorizes work into three buckets:
| Category | Description | Location |
|---|---|---|
| Android-Specific | Platform APIs, navigation, layouts | amethyst/, androidMain/ |
| Reusable (Shared) | Business logic, UI components, state | quartz/commonMain/, commons/ (convert to KMP) |
| Desktop-Specific | Desktop navigation, layouts, platform APIs | desktopApp/, jvmMain/ |
Step 3: Code Sharing Strategy
Share:
- Business logic and data models →
quartz/commonMain/ - Major UI components (cards, lists, dialogs) →
commons/(convert to KMP as needed) - State management and ViewModels → shared
- Icons and visual assets →
commons/commonMain/
Keep Platform-Native:
- Navigation patterns (sidebar vs bottom nav)
- Screen layouts and scaffolding
- Platform-specific interactions (gestures, keyboard shortcuts)
- System integrations (notifications, file pickers)
Step 4: Extract Shared Components
When extracting UI components:
- Identify reusable composables in Android code
- Move to
commons/commonMain/(consult/compose-expertfor patterns) - Create expect/actual declarations for platform-specific behavior (consult
/kotlin-multiplatform) - Update both Android and Desktop to use shared component
Note: quartz/ is protocol-only (no composables). Shared UI goes in commons/ after converting it to KMP.
Build Commands
# Run desktop app
./gradlew :desktopApp:run
# Run Android app
./gradlew :amethyst:installDebug
# Build Quartz for all targets
./gradlew :quartz:build
# Run tests
./gradlew test
# Format code
./gradlew spotlessApply
Quartz KMP Structure
The Quartz library uses expect/actual for platform-specific implementations:
// commonMain - shared protocol logic
expect class CryptoProvider {
fun sign(message: ByteArray, privateKey: ByteArray): ByteArray
fun verify(message: ByteArray, signature: ByteArray, publicKey: ByteArray): Boolean
}
// androidMain - uses secp256k1-kmp-jni-android
actual class CryptoProvider { /* Android implementation */ }
// jvmMain - uses secp256k1-kmp-jni-jvm
actual class CryptoProvider { /* JVM implementation */ }
Key Patterns
Platform Abstraction
// commonMain
expect fun openExternalUrl(url: String)
// androidMain
actual fun openExternalUrl(url: String) {
context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
}
// jvmMain (Desktop)
actual fun openExternalUrl(url: String) {
Desktop.getDesktop().browse(URI(url))
}
Navigation Shell
- Desktop: Sidebar + main content area
- Android: Bottom navigation
Git Workflow
- Branch:
feat/desktop-<feature>orfix/desktop-<issue> - Commits: Conventional commits (
feat:,fix:, etc.) - Never use
--no-verify