Wires the workspace through `cargo apk build`. After this commit `cargo apk build -p solitaire_app --target x86_64-linux-android` produces a debug-signed APK at `target/debug/apk/solitaire-quest.apk` containing all assets and `lib/x86_64/libsolitaire_app.so` — runnable on the AVD or a physical x86_64 device. The five gating points discovered by iterating compile cycles: 1. solitaire_app split into bin + lib. cargo-apk needs a `cdylib` to bundle as `libmain.so`; pure-bin crates panic with "Bin is not compatible with Cdylib". `src/lib.rs` carries the ECS bootstrap as `pub fn run`; `src/main.rs` is a 3-line shim that delegates for the desktop `cargo run` path. 2. `[package.metadata.android]` pins target SDK 34 / min SDK 26 so cargo-apk doesn't probe for whatever default it ships (which on this machine was an uninstalled API 30). `assets = "../assets"` lets the same asset directory feed both desktop and APK. 3. Workspace `bevy` features add `android-native-activity` (the Bevy-side glue that pairs with cargo-apk's NativeActivity wrapper). The feature is target-gated inside bevy_internal so desktop builds compile it out. 4. `arboard` (clipboard, used by Stats's "Copy share link") has no Android backend — `cargo apk build` fails with E0433 on `platform::Clipboard` if unconditional. Target-gated to `cfg(not(target_os = "android"))`; the system surfaces an informational toast on Android until JNI ClipboardManager is wired in the Phase-Android round. 5. `keyring` + `keyring-core` cannot compile for android — the transitive `rpassword` uses `libc::__errno_location` which bionic doesn't expose. Both crates target-gated; `auth_tokens` ships a stub on Android that returns `KeychainUnavailable` for every call, matching how callers already handle a Linux box without Secret Service. Cosmetic post-pass panic: cargo-apk panics AFTER the APK is signed when it tries to also wrap the bin target. The APK on disk is unaffected. Working around this with `cargo apk build --lib` is the next small step. What's verified: - Desktop `cargo build`, `cargo clippy --workspace --all-targets`, and `cargo test --workspace` all clean. - `cargo apk build -p solitaire_app --target x86_64-linux-android` produces 54 MB debug APK with libsolitaire_app.so + assets. What's NOT yet verified: - Whether the APK actually launches on the AVD / a phone (next step: `adb install` + `adb logcat` against the bevy_test AVD). - Whether `dirs::data_dir()` on Android returns a usable path (sync / persistence will surface this if not). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Solitaire Quest
A cross-platform Klondike Solitaire game written in Rust, with a card-theme system, full progression (XP / levels / achievements / daily challenges), and optional self-hosted sync so your stats follow you across machines.
Features
- Klondike Solitaire — Draw One and Draw Three modes; foundations are unlocked (any Ace lands in any empty slot, the slot then claims that suit)
- Card themes — bundled hayeah/playing-cards-assets default plus user-installable themes (drop a directory under the data dir or import a zip from Settings → Cosmetic)
- Modern HUD — reserved top band keeps cards from crowding the score readout; the action bar auto-fades when the cursor leaves it so it can't compete with the play surface
- Drag feel — every legal drop target is highlighted in green during drag; cards cast a soft drop shadow that lifts when picked up; the stock pile shows a remaining-count chip so you can see how close you are to a recycle
- Keyboard navigation — Tab cycles focus through buttons, arrow keys move within picker rows, Enter activates; works across every modal and the HUD action bar
- Progression — XP, levels, unlockable card backs and backgrounds
- 19 Achievements — including secret ones
- Daily Challenge — server-seeded so every player worldwide gets the same deal
- Leaderboard — opt-in, powered by your own self-hosted server
- Special Modes (unlocked at level 5): Zen, Time Attack, Challenge
- Sync — pull/push stats across devices via a self-hosted server
- Color-blind mode — blue tint on red-suit cards alongside the suit glyph
Building
Prerequisites
- Rust stable toolchain (
rustup install stable) - Linux:
libasound2-dev libudev-dev libxkbcommon-dev - macOS: Xcode Command Line Tools
# Fast development build
cargo run -p solitaire_app --features bevy/dynamic_linking
# Release build
cargo build -p solitaire_app --release
./target/release/solitaire_app
Controls
Every action also has a visible UI button — keyboard shortcuts are optional accelerators.
| Key | Action |
|---|---|
| Left click / drag | Move cards |
| Double click | Auto-move card to its best legal destination |
| Right click | Highlight legal moves for a card |
| Space / D | Draw from stock |
| U | Undo |
| H | Hint (highlight a legal move) |
| N | New game |
| Z | Zen mode |
| G | Forfeit (during pause) |
| Tab / Shift+Tab | Cycle keyboard focus |
| Enter | Activate focused button / auto-complete (when badge is lit) |
| Esc | Pause / dismiss modal |
| F1 | Help / controls |
| F11 | Toggle fullscreen |
| S / A / P / O / L / M | Stats / Achievements / Profile / Settings / Leaderboard / Menu |
Card themes
The default theme ships embedded in the binary, so the game runs
self-contained with no external assets. To install another theme, drop a
directory containing a theme.ron manifest plus 53 SVG files (52 faces +
1 back) under the platform data dir's themes/ folder, or import a zip
from Settings → Cosmetic. The picker chip lights up the moment a new
theme is registered. Themes are SVG-based, so they rasterise cleanly at
whatever resolution the window happens to be.
Sync Server (optional)
To sync stats across machines, run the self-hosted server. See README_SERVER.md for setup instructions.
Once the server is running, open Settings → Sync Backend, enter the server URL and your username, and register an account from within the game.
Running Tests
# All tests (982 passing as of v0.11.0)
cargo test --workspace
# Just game logic (no display required)
cargo test -p solitaire_core -p solitaire_sync -p solitaire_data -p solitaire_server
# Lint
cargo clippy --workspace --all-targets -- -D warnings
Credits
Built on Bevy and the wider Rust ecosystem
(Tokio, Axum, sqlx, Serde, kira, and many more). Card faces come from
hayeah/playing-cards-assets
(MIT, derived from the public-domain vector-playing-cards library); the
default card back is original work; the UI font is FiraMono-Medium (OFL).
All audio is synthesized programmatically by this project. See
CREDITS.md for the full list and license details.
Changelog
See CHANGELOG.md.
License
MIT — see LICENSE.