This document outlines the strategy for creating, maintaining, and releasing an Avalonia port of BabySmash!, enabling the application to run on Linux while maintaining the existing WPF version for Windows.
Current State: WPF application targeting .NET 10, Windows-only
Target State: WPF for Windows (existing) + Avalonia for Linux (new)
Timeline: 2-3 month phased implementation
Maintenance Strategy: Shared business logic, platform-specific UI
- Why Avalonia?
- Architecture Strategy
- Technical Analysis
- Implementation Phases
- Maintenance Strategy
- Release Strategy
- Risk Assessment
- Success Criteria
- Linux Support: Bring BabySmash to Linux users and education environments
- Modern .NET: Built for .NET 6+ with excellent performance
- XAML Similarity: Minimal learning curve - reuse WPF XAML with minor changes
- Active Development: Strong community and commercial backing
- Raspberry Pi: Great for educational use on ARM Linux devices
- Linux Desktop: Parents using Ubuntu, Fedora, or other Linux distributions
- Education Environments: Schools and libraries running Linux
- Raspberry Pi: Educational computing devices (x64 and ARM64)
- ChromeOS Linux Mode: Chromebooks with Linux container support
- Community Growth: Expand user base to the Linux community
Maintain separate WPF (Windows) and Avalonia (Linux) projects with shared business logic.
BabySmash.sln
├── BabySmash.csproj (existing - WPF for Windows)
│ ├── WPF-specific UI (XAML, code-behind)
│ └── Windows-specific features (keyboard hooks, System.Speech)
├── BabySmash.Linux (new - Avalonia for Linux)
│ ├── Avalonia UI (XAML ported from WPF)
│ └── Linux-specific implementations
└── BabySmash.Core (new - shared library)
├── Controller.cs (platform-agnostic logic)
├── Shapes (core shape definitions)
├── WordFinder.cs
├── Settings.cs (abstracted storage)
└── Models & ViewModels
Pros:
- Clean separation of concerns
- Windows version remains unchanged (WPF)
- Linux gets native support via Avalonia
- Lower risk - only adding Linux support
- Can ship incrementally
Cons:
- Two UI codebases to maintain (but shared core logic)
- Need to sync major features between platforms
Replace WPF entirely with Avalonia.
Pros: Single codebase
Cons: Lose Windows-specific features, high risk, all-or-nothing approach
| Component | WPF Implementation (Windows) | Avalonia for Linux | Complexity |
|---|---|---|---|
| XAML UI | WPF XAML | Avalonia XAML | |
| Shapes | 14 custom UserControls | Port to Avalonia UserControls | ✅ Low |
| Animations | WPF Storyboards | Avalonia Animations | ✅ Low |
| Text-to-Speech | System.Speech (Windows) | espeak/speech-dispatcher | |
| Keyboard Hooks | Win32 P/Invoke | X11/Wayland capture | 🔴 High |
| Audio | P/Invoke winmm.dll | NAudio or ALSA/PulseAudio | |
| Multi-Monitor | System.Windows.Forms.Screen | Avalonia.Platform.Screen | ✅ Low |
| Settings | .NET Settings (Windows) | JSON in ~/.config | ✅ Low |
| Auto-Update | Updatum (GitHub Releases) | Same (Updatum works on Linux) | ✅ Low |
WPF (Windows): System.Speech.Synthesis.SpeechSynthesizer
Avalonia (Linux): Use espeak or speech-dispatcher via CLI or P/Invoke
Implementation Options:
- espeak: Widely available on Linux, lightweight, supports many languages
- speech-dispatcher: More sophisticated, better voice quality
- Festival: Alternative TTS engine
Recommendation: Create ITtsService interface with platform implementations
public interface ITtsService
{
void Speak(string text);
void SetLanguage(CultureInfo culture);
}
// Implementations:
// - TtsService.Windows.cs (System.Speech) - existing WPF
// - TtsService.Linux.cs (espeak wrapper) - new AvaloniaWPF (Windows): Low-level keyboard hook via Win32 API to intercept ALL keys (prevent Alt+Tab, etc.)
Avalonia (Linux): Use XGrabKeyboard (X11) or input capture on Wayland
Implementation Options:
- X11:
XGrabKeyboardfor full keyboard capture - Wayland: May require different approach (compositor-specific)
- Fallback: Use standard Avalonia keyboard events (less comprehensive)
Challenge: Permission requirements on Linux (may need specific user groups)
Recommendation: Implement IKeyboardHookService with Linux-specific implementation
WPF (Windows): Direct P/Invoke to winmm.dll for WAV playback
Avalonia (Linux): Use NAudio or native ALSA/PulseAudio
Implementation Options:
- NAudio: Works on Linux with ALSA/PulseAudio backend
- ALSA direct: Lower-level Linux audio
- PulseAudio: Higher-level audio server (most common on modern Linux)
- System.Media.SoundPlayer: Simple but limited
Recommendation: Use NAudio with IAudioService abstraction
public interface IAudioService
{
void PlaySound(string resourceName);
}
// - AudioService.Windows.cs (winmm.dll) - existing WPF
// - AudioService.Linux.cs (NAudio/ALSA) - new AvaloniaWPF (Windows): Uses Properties.Settings (Windows Registry or user.config XML)
Avalonia (Linux): Store JSON settings in user directory
- Linux:
~/.config/babysmash/settings.json
Implementation: Use simple System.Text.Json serialization
public interface ISettingsService
{
T Get<T>(string key, T defaultValue);
void Set<T>(string key, T value);
void Save();
}Most WPF XAML translates directly to Avalonia with minor changes:
| WPF Feature | Avalonia Equivalent | Notes |
|---|---|---|
Window |
Window |
✅ Same |
Grid, StackPanel, Canvas |
Same | ✅ Same |
TextBlock, Button |
Same | ✅ Same |
UserControl |
UserControl |
✅ Same |
Storyboard |
Storyboard (in Animation namespace) |
|
BitmapEffect |
Effect (use DropShadowEffect) |
|
DispatcherTimer |
DispatcherTimer |
✅ Same |
x:Name |
x:Name or Name |
✅ Same |
Incompatibilities:
- No
AllowsTransparencyon Windows - use compositor APIs instead - Some easing functions have different names
BitmapEffectis already removed in current WPF version (good!)
Goal: Extract shared business logic into BabySmash.Core
- Create
BabySmash.Core(.NET Standard 2.0 or .NET 6+ class library) - Move platform-agnostic code to Core:
-
Controller.cs(refactor to remove WPF dependencies) -
WordFinder.cs - Shape models/definitions
-
Settings.cs(create abstraction) - Extension methods
-
- Define platform abstraction interfaces:
-
ITtsService(text-to-speech) -
IAudioService(sound playback) -
IKeyboardHookService(keyboard interception) -
ISettingsService(cross-platform settings) -
IScreenService(multi-monitor support)
-
- Update WPF project to reference
BabySmash.Core - Verify WPF app still works after refactoring
Deliverable: Working WPF app using shared Core library
Goal: Create basic Avalonia project structure for Linux
- Create
BabySmash.LinuxAvalonia project- Target:
net10.0with Avalonia 11.x - Platform:
linux-x64(and optionallylinux-arm64for Raspberry Pi)
- Target:
- Add Avalonia NuGet packages:
<PackageReference Include="Avalonia" Version="11.2.0" /> <PackageReference Include="Avalonia.Desktop" Version="11.2.0" /> <PackageReference Include="Avalonia.Themes.Fluent" Version="11.2.0" />
- Reference
BabySmash.Coreproject - Create basic
App.axamlandMainWindow.axaml - Embed resources (sounds, Words.txt, localization JSON)
- Configure Linux publishing
Deliverable: Empty Avalonia app that launches on Linux
Goal: Implement main game UI with shapes and animations
- Port
MainWindow.xamltoMainWindow.axaml- Canvas layout for shapes
- Info label (Ctrl+Alt+Shift+O, Alt+F4 instructions)
- Update notification area
- Port 14 shape UserControls to Avalonia:
CoolCircle,CoolOval,CoolSquare,CoolStar, etc.- Convert animations to Avalonia
AnimationAPI - Test face animations and colors
- Port
Options.xamltoOptions.axaml- Complex 64KB XAML with many controls
- May need to simplify or redesign for cross-platform
- Implement multi-monitor support
- Use
Avalonia.Platform.Screen.AllScreens - Create window per monitor (same as WPF)
- Use
Deliverable: Avalonia app displays shapes on keypress (without sound/speech)
Goal: Implement Linux-specific services (TTS, audio, keyboard hooks)
- Linux:
TtsService.Linux.csusingespeakorspeech-dispatcher - Test with multiple languages (en, ru, pt)
- Handle missing TTS gracefully (fallback to no speech)
- Choose audio library (NAudio with ALSA/PulseAudio backend)
- Implement
AudioService.Linux.csfor WAV playback - Embed WAV resources (10 sound files)
- Test on Ubuntu, Fedora, Arch Linux
- Linux: Implement using X11
XGrabKeyboardor Wayland equivalent - Handle both X11 and Wayland display servers
- Test Alt+Tab blocking, Super key blocking
- Handle permission requirements (user groups if needed)
- Implement
SettingsService.Linux.cs - Use JSON storage in
~/.config/babysmash/settings.json - Test settings persist across app restarts
Deliverable: Fully functional Linux app with sound, speech, and keyboard hooks
Goal: Implement auto-update and Linux packaging
- Configure Updatum for Linux
- Linux:
BabySmash-linux-x64.ziporBabySmash-linux-x64.tar.gz
- Linux:
- Port
UpdateDialog.xamlto Avalonia (if not already done) - Port
DownloadProgressDialog.xamlto Avalonia (if not already done) - Test update flow on Linux
- AppImage: Create portable AppImage (most compatible)
- Optional: Flatpak manifest for Flathub
- Optional: Snap package for Snap Store
- Optional: .deb package for Debian/Ubuntu
- Optional: .rpm package for Fedora/RHEL
Deliverable: Auto-updating Linux app with portable distribution format
Goal: Automate Linux builds
- Create
.github/workflows/build-linux.ymlor extend existing workflow - Build matrix for Linux platforms:
ubuntu-latest: linux-x64- Optional: linux-arm64 for Raspberry Pi
- Create Linux packages:
- AppImage (primary)
- Tarball (.tar.gz)
- Optional: .deb, .rpm, Flatpak, Snap
- Upload to GitHub Releases
Sample Workflow Structure:
jobs:
build-linux:
runs-on: ubuntu-latest
steps:
- Build linux-x64
- Create AppImage
- Create tarball
- Upload artifactsDeliverable: Automated Linux releases on GitHub
Goal: Comprehensive testing on Linux and user experience improvements
- Functionality Testing on Linux:
- All shapes display correctly
- Animations work smoothly (60 FPS)
- Audio plays on keypress
- Text-to-speech works (espeak/speech-dispatcher)
- Multi-monitor support
- Options dialog saves settings
- Auto-update downloads and installs
- Keyboard shortcuts work (Ctrl+Alt+Shift+O, Alt+F4)
- Platform-Specific Testing:
- Test on Ubuntu 22.04+ (GNOME, X11 and Wayland)
- Test on Fedora (GNOME, Wayland)
- Test on Arch Linux (KDE, X11)
- Test on Linux Mint (Cinnamon)
- Optional: Test on Raspberry Pi OS (ARM64)
- Performance Testing:
- No lag when mashing keyboard rapidly
- Low CPU usage when idle (<5%)
- Memory usage stays reasonable (<200MB)
- Accessibility:
- Keyboard navigation
- Screen reader compatibility (Orca on Linux)
- UI Polish:
- Consistent look with Linux desktop themes
- Native window decorations
- Proper icon integration
Deliverable: Production-ready Linux version
All business logic lives in BabySmash.Core:
- Shape generation logic
- Word finding
- Settings management (abstracted)
- Animation definitions
- Color palettes
Benefit: Fix once, both Windows (WPF) and Linux (Avalonia) benefit
BabySmash.csproj: Windows WPF version (existing, no changes)BabySmash.Linux: Linux Avalonia version (new)
When to change:
- Core change (new shape, word list update): Update
BabySmash.Core - UI improvement: Update both WPF and Avalonia (or decide platform priority)
- Platform-specific feature: Update only that platform's project
Approach: WPF (Windows) remains the primary platform, Linux follows
- New features developed in WPF first (existing userbase)
- Port to Linux within same or next release cycle
- Eventually, both platforms reach feature parity
- Linux-specific features (if any) can be Linux-only
- Update README with platform-specific installation instructions
- Create
BUILDING_AVALONIA.mdfor contributors - Maintain platform compatibility matrix
Use semantic versioning with platform indication in release notes:
v5.0.0- First Linux release (major version bump)v5.0.1- Bugfix for both platformsv5.1.0- New feature in both WPF and Linux
Each release includes:
| File | Platform | Description |
|---|---|---|
BabySmash-Setup.exe |
Windows | WPF installer (existing) |
BabySmash-win-x64.zip |
Windows | WPF portable (existing, Updatum target) |
BabySmash-linux-x64.AppImage |
Linux | Avalonia AppImage (new) |
BabySmash-linux-x64.tar.gz |
Linux | Avalonia portable (new) |
BabySmash-linux-arm64.AppImage |
Linux (ARM) | Optional: Raspberry Pi support |
- Primary: GitHub Releases (WPF version - existing, no changes)
- Future: Microsoft Store (if desired)
- Primary: GitHub Releases (AppImage + tarball)
- Future: Flatpak (Flathub) - community-maintained
- Future: Snap Store - community-maintained
- Future: Distribution repos (apt, dnf, pacman) - community-maintained
Configure Updatum to support Windows (WPF) and Linux (Avalonia) flavors:
// WPF version (Windows-only) - existing, no changes
var wpfUpdater = new UpdatumManager("shanselman", "babysmash")
{
AssetRegexPattern = "BabySmash-win-x64.zip",
};
// Linux Avalonia version (new)
var linuxUpdater = new UpdatumManager("shanselman", "babysmash")
{
AssetRegexPattern = "BabySmash-linux-x64.(AppImage|tar.gz)",
};| Risk | Severity | Likelihood | Mitigation |
|---|---|---|---|
| Avalonia XAML incompatibilities | Medium | Medium | Incremental porting, test each shape |
| Linux keyboard hook permissions | High | High | Clear documentation, graceful fallback |
| Linux TTS quality/availability | Medium | Medium | Provide alternative (visual-only mode) |
| X11 vs Wayland differences | Medium | Medium | Test both, provide compatibility layer |
| Audio issues on some Linux distros | Low | Low | Use well-tested library (NAudio with ALSA/PulseAudio) |
| Performance on older hardware | Low | Low | Profile early, optimize as needed |
| Risk | Severity | Mitigation |
|---|---|---|
| Maintenance burden (2 UI codebases) | Low | Shared Core library reduces duplication to ~20% |
| Limited Linux user demand | Low | Release as beta, gauge interest |
| Linux distro fragmentation | Medium | Use AppImage (universal), test on major distros |
| Support burden from Linux users | Medium | Community-driven support, clear docs |
- Shared Core Library: 80% of code shared, only 20% platform-specific UI
- Gradual Rollout: Release Linux version as "beta" initially, gather feedback
- Community Engagement: Recruit Linux testers from community
- Fallback Options: If a feature is unavailable on Linux, degrade gracefully (e.g., no TTS → visual-only mode)
- All shapes display correctly on Linux
- Animations run smoothly (60 FPS)
- Audio plays on keypress
- Text-to-speech works (espeak/speech-dispatcher)
- Multi-monitor support works
- Options dialog saves settings
- Auto-update downloads and installs updates
- Keyboard shortcuts work (Ctrl+Alt+Shift+O, Alt+F4)
- Windows: WPF version continues to work (no regressions)
- Linux: AppImage runs on Ubuntu, Fedora, Arch, Linux Mint
- Linux: Works on both X11 and Wayland
- Linux (Optional): Works on Raspberry Pi (ARM64)
- No crashes during 10-minute keyboard mashing session
- CPU usage < 5% when idle
- Memory usage < 200MB
- Startup time < 2 seconds
- 10+ downloads of Linux version in first month
- At least 1 community contribution (bug report or PR)
- Positive feedback from Linux users
- No regression issues from Windows WPF users
- Phase 1-3 (Core + Basic UI): 4-6 weeks
- Phase 4 (Linux Services): 2-3 weeks
- Phase 5-7 (Update, Packaging, Testing): 2-3 weeks
Total: ~2-3 months for v1.0 Linux release
- GitHub Actions: Free (within limits)
- No code signing costs for Linux (optional for Flatpak/Snap)
Total: ~$0/year incremental cost (Linux doesn't require paid code signing)
- Existing WPF development continues in parallel
- No blocking of current feature roadmap
- Can be done incrementally (community contributions welcome)
The Avalonia port of BabySmash! for Linux is technically feasible and strategically valuable for reaching Linux users while keeping the existing Windows WPF version unchanged. The dual-codebase approach with a shared BabySmash.Core library minimizes maintenance burden.
- Phase 1-2 (4-5 weeks): Extract Core, create Avalonia skeleton for Linux
- Phase 3-4 (4-6 weeks): Port UI and implement Linux-specific services
- Phase 5-7 (2-3 weeks): Auto-update, packaging, testing
- Release: v5.0.0 with WPF (Windows) and Avalonia (Linux)
- Approval: Decide if Linux support aligns with project goals
- Resource Allocation: Assign developer time or open to community contributions
- Pilot: Start with Phase 1 (Core library extraction) as low-risk first step
- Community: Announce intent, gauge interest from Linux users
Decision Point: Proceed with Phase 1 or defer until more demand is evident?
- Avalonia Music Store - Complete sample app
- Markdown Monster (WPF to Avalonia) - Migration experience
Document Version: 1.0
Created: January 2026
Author: GitHub Copilot Workspace (AI Planning Agent)
Status: DRAFT - Awaiting Review