This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
LunaDraw is a child-centric drawing application (ages 3-8) built with .NET MAUI targeting Windows, Android, iOS, and MacCatalyst. The app features 24+ magical brush effects, shape tools, stamps, undo/redo, layer management, and "Movie Mode" time-lapse replay.
Important Context:
- The codebase is heavily AI-generated ("vibe-coded") and can be fragile in places
- Some canvas functionality was migrated from a working app in
\Legacy\SurfaceBurnCalc - The app is in active development with missing features tracked in
Documentation/MissingFeatures.md
# Build the project (Windows target)
dotnet build LunaDraw.csproj -f net10.0-windows10.0.19041.0
# Build for specific platform
dotnet build LunaDraw.csproj -f net10.0-android36.0
dotnet build LunaDraw.csproj -f net10.0-ios26.0
dotnet build LunaDraw.csproj -f net10.0-maccatalyst26.0# Run all tests
dotnet test tests/LunaDraw.Tests/LunaDraw.Tests.csproj
# Run specific test
dotnet test tests/LunaDraw.Tests/LunaDraw.Tests.csproj --filter "FullyQualifiedName~TestMethodName"- Use Visual Studio 2022 or VS Code with C# Dev Kit and .NET MAUI extensions
- Select target framework (e.g.,
net10.0-windows10.0.19041.0) - Build and Run through IDE
- .NET MAUI - Cross-platform UI framework
- SkiaSharp - All vector graphics and rendering (primary graphics engine)
- ReactiveUI - MVVM framework and state management using observables
- CommunityToolkit.Maui - Extended MAUI controls and utilities
- ViewModels inherit from
ReactiveObjectfor property change notifications - Use
this.RaiseAndSetIfChanged(ref field, value)for reactive properties - Leverage reactive subscriptions for messaging and state changes
- MessageBus (ReactiveUI's
IMessageBus): Use sparingly for loosely-coupled broadcast messages between disconnected components - Reactive Observables: Preferred approach for component communication where possible
- Command/Event Pattern: Fallback when reactive approaches don't fit
- MessageBus is instance-based (injected via DI), NOT static for testability
Services registered in MauiProgram.cs:
- Core State:
IMessageBus,NavigationModel,SelectionObserver,ILayerFacade - Logic Services:
ICanvasInputHandler,ClipboardMemento,IBitmapCache,IPreferencesFacade,IDrawingStorageMomento - ViewModels: Singleton or Transient as appropriate
- Pages: Typically Transient
-
IDrawableElement: Base interface for all drawable objects (paths, shapes, stamps, images)
- Supports selection, transforms, visibility, layering (ZIndex), opacity, fill/stroke
- Each element has
Bounds,TransformMatrix, and methods:Draw(),HitTest(),Clone(),Translate(),Transform() - Concrete implementations:
DrawablePath,DrawableEllipse,DrawableRectangle,DrawableLine,DrawableImage,DrawableStamps,DrawableGroup
-
Layer: Container for drawable elements with ReactiveUI observable collections
- Uses QuadTree spatial indexing (
QuadTreeMemento<IDrawableElement>) for efficient spatial queries and rendering - No bitmap tiling - renders directly from vector elements
- Auto-assigns ZIndex to new elements to maintain draw order
- Supports masking modes, visibility, locking
- Uses QuadTree spatial indexing (
-
ILayerFacade: Abstraction for layer management operations
- Manages
ObservableCollection<Layer>and current layer state - Integrates with
HistoryMementofor undo/redo - Methods:
AddLayer(),RemoveLayer(),MoveLayer(),MoveElementsToLayer(),SaveState()
- Manages
- IDrawingTool: Interface for all drawing/editing tools
- Tool implementations:
FreehandTool,EraserTool,EraserBrushTool,FillTool,SelectTool,LineTool,RectangleTool,EllipseTool,ShapeTool - Tools receive
ToolContextwith canvas state, navigation, layers, and brush settings - Input handling delegated to
CanvasInputHandlerwhich dispatches to active tool
- NavigationModel: Manages pan/zoom transformations via
ViewMatrix(SKMatrix) - CanvasInputHandler: Central touch/mouse input processor
- Handles multi-touch gestures (pan, zoom, rotate) on canvas and selection
- Delegates single-touch drawing to active tool
- Right-click switches to Select tool
- Applies smoothing to gestures for fluid interaction
- MainPage: Primary page hosting
SKCanvasViewfor rendering- Subscribes to
CanvasInvalidateMessageto trigger redraws - Manages context menus and flyout panels (brushes, shapes, settings)
- Subscribes to
- HistoryMemento: Undo/redo stack for layer states
- ClipboardMemento: Copy/paste buffer for drawable elements
- DrawingStorageMomento: Serialization/deserialization of drawings to file
- QuadTreeMemento: Generic spatial partitioning for efficient hit-testing and culling
- Test Format: Arrange-Act-Assert (AAA)
- If no
// Arrangeneeded, start with// Act
- If no
- Naming:
Should_When_Returnsformat- Example:
Should_Set_Sliding_Issued_At_Time_When_Valid_Credentials_Expired_Or_Invalid_Returns_Logout
- Example:
- Test Instances: Use class name for instance, NOT 'sut' or arbitrary names
- Mocks:
mockClassName(e.g.,mockLayerFacade)
- Mocks:
- Assertions: One assertion per line
- Test Types: Prefer
[Theory],[InlineData],[MemberData]over multiple[Fact]methods. Include negative test cases
- Write test first to validate the bug exists
- Implement the fix
- Run test to confirm bug elimination
- NO underscores in names
- NO regions
- NO abbreviations in variable names or otherwise (use full descriptive names)
- NO legacy or duplicate code - refactor to clean state, remove obsolete code
- Static extensions: Use ONLY for reusable logic (see
Logic/Extensions/)
Ensure adherence to:
- Single Responsibility Principle (SRP)
- Open/Closed Principle (OCP)
- Liskov Substitution Principle (LSP)
- Interface Segregation Principle (ISP)
- Dependency Inversion Principle (DIP)
- DRY (Don't Repeat Yourself)
- Low Coupling / High Cohesion
- Separation of Concerns & Modularity
LunaDraw/
├── Components/ # Reusable UI components and controls
│ ├── Carousel/ # Gallery carousel implementation
│ ├── *FlyoutPanel.xaml # Brush, shape, settings panels
│ └── *.cs # Custom controls (BrushPreview, ShapePreview, etc.)
├── Converters/ # XAML value converters
├── Documentation/ # Architecture, features, missing features
├── Logic/ # Core business logic (non-UI)
│ ├── Constants/ # App-wide constants
│ ├── Extensions/ # Static extension methods (SkiaSharp, Preferences)
│ ├── Handlers/ # Input handling (CanvasInputHandler)
│ ├── Messages/ # MessageBus message types
│ ├── Models/ # Domain models (IDrawableElement, Layer, ToolContext, etc.)
│ ├── Tools/ # IDrawingTool implementations
│ ├── Utils/ # Utilities (LayerFacade, Mementos, BitmapCache, etc.)
│ └── ViewModels/ # ReactiveUI ViewModels
├── Pages/ # MAUI pages (MainPage)
├── Platforms/ # Platform-specific code
├── Resources/ # Images, fonts, splash, raw assets
├── tests/ # Unit tests
│ └── LunaDraw.Tests/
└── MauiProgram.cs # DI registration and app configuration
- All graphics rendered via SkiaSharp (
SKCanvas,SKPaint,SKPath) MainPage.OnCanvasViewPaintSurface: Main rendering loop- Applies
NavigationModel.ViewMatrixfor pan/zoom - Iterates layers, uses QuadTree to cull off-screen elements
- Elements sorted by ZIndex before drawing
- Applies
- 24+ brush effects with custom shaders and blending modes
- Examples: Glow/Neon (additive blending, bloom), Star Sparkles, Rainbow, Fireworks, Crayon, Spray, Ribbon
- Brush settings stored in
ToolbarViewModeland passed viaToolContext
- Records drawing process in background
- Playback animates creation of drawing
- Large touch targets (min 2cm x 2cm)
- Multi-sensory feedback (sounds, animations)
- Icon-driven, minimal text
- Visual/audio guidance over explicit instructions
- Canvas functionality migrated from
\Legacy\SurfaceBurnCalc(previous working app) - Current branch
reactive-carousel-v2is refactoring carousel infrastructure from SBC to MAUI - Code is fragile in places due to AI generation - test thoroughly
- README.md: Project overview, features, screenshots, setup
- Documentation/ArchitectureDesign.md: Detailed architecture and design requirements
- Documentation/Features.md: Feature specifications
- Documentation/MissingFeatures.md: Pending features and known issues
- .clinerules/: Coding standards and SPARC methodology guidelines