Files
Cable/CLAUDE.md
Stefan Lange-Hegermann 03878b9507 Add analytics tracking, overview PDF export, and charger updates
Add first launch event, share tracking for overview PDF and diagram
exports. Add SystemOverviewPDFExporter for A4 PDF generation. Update
charger model with new configuration fields and localization for all
5 languages. Refresh app icon assets and CLAUDE.md build instructions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 17:45:54 +01:00

3.4 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Build & Test Commands

Use the Xcode MCP server tools instead of xcodebuild CLI:

  • List windows first: Always run mcp__xcode__XcodeListWindows to find the correct tabIdentifier — it changes depending on which Xcode windows are open.
  • Build: mcp__xcode__BuildProject
  • Run all tests: mcp__xcode__RunAllTests
  • Check errors: mcp__xcode__GetBuildLog (severity: error) or mcp__xcode__XcodeListNavigatorIssues

No external dependencies beyond the Xcode toolchain.

Architecture

SwiftUI + SwiftData app for sizing low-voltage electrical conductors (boats, RVs, off-grid).

Data Model Hierarchy

ElectricalSystem (top-level container) owns collections of:

  • SavedLoad — individual electrical loads with wire sizing parameters
  • SavedBattery — battery banks with chemistry-specific capacity rules
  • SavedCharger — charging equipment specs

All are @Model classes persisted via SwiftData. The container is configured in CableApp.swift and injected into the SwiftUI environment.

Key Layers

  • Calculation engine (Loads/ElectricalCalculations.swift): Pure static functions for wire cross-section sizing, voltage drop, power loss, and fuse recommendations. Uses copper resistivity (0.017 Ω·mm²/m) with a 5% max voltage drop constraint. Supports both metric (mm²) and imperial (AWG) wire standards.
  • CableCalculator (Loads/CableCalculator.swift): ObservableObject wrapper that bridges the calculation engine to SwiftUI views.
  • App-wide state: UnitSystemSettings (metric/imperial, persisted to UserDefaults) and StoreKitManager (subscription status) are injected as @EnvironmentObject.

Navigation Flow

SystemsView (root list) → LoadsView (per-system TabView with 4 tabs: Overview, Components, Batteries, Chargers) → individual editor modals for each entity type.

Feature Organization

Each feature has its own directory under Cable/: Loads/, Systems/, Batteries/, Chargers/, Overview/, Paywall/. Models and views for each feature live together.

Code Style

  • 4-space indentation, trailing commas on multiline collections, 120-char soft line limit
  • UpperCamelCase for types, lowerCamelCase for methods/properties
  • Test naming: testScenario_expectedResult
  • Commit messages: short imperative subjects under 50 characters

Localization

5 languages: English (base), German, Spanish, French, Dutch. Translation files are in *.lproj/Localizable.strings and Localizable.stringsdict.

  • Use String(localized:defaultValue:)not NSLocalizedString. The defaultValue serves as English fallback and avoids showing raw keys when a Localizable.strings entry is missing.
  • When adding new user-facing strings, add translations to all 5 Localizable.strings files immediately.

PDF Export Pattern

PDF exports use UIGraphicsPDFRenderer with A4 portrait format. The pattern is:

  • Exporter struct (e.g. SystemOverviewPDFExporter, SystemBillOfMaterialsPDFExporter) with snapshot data types — keeps Core Graphics rendering isolated from SwiftUI/SwiftData.
  • ShareSheet triggered via @State item binding in the parent view.
  • Toolbar button (not inline content) for the export action.

StoreKit

Subscription product IDs: app.voltplan.cable.weekly, app.voltplan.cable.yearly. Pro features are gated via StoreKitManager.isPro.