Work

Projects

An application I created, a few demonstrators published on GitHub, and a case study of porting the application to a second platform.

Applications

My projects

Allure+

Live on iOS · Android in progress

Training and performance tracking app. I created it on iOS. The Android port is in progress. The showcase site presents the features and news.

  • iOS
  • SwiftUI
  • Android (in progress)
  • Kotlin
  • Jetpack Compose
  • Sport
allureplus.app (new tab)

Open source

Demonstrators

Short tools, written to be read and reused. The code is on GitHub, with documentation in French and English.

Architecture and .NET

An Azure project base and two reusable libraries.

  • Starter .NET 10 and Azure (new tab)

    Minimal API that publishes events to Azure Service Bus. Pure domain, tests, Bicep and CI, no secrets (managed identity and RBAC).

    • .NET 10
    • Azure
    • Bicep
    • CI/CD
  • SFerrand.Http (new tab)

    Base class for writing typed REST and GraphQL clients in .NET. HTTP errors are a result, not an exception. Retries with backoff, idempotency keys, pagination, controlled redirects (credentials never leave the origin of the call) and OpenTelemetry traces. A test package comes with the library.

    • C#
    • .NET 8+
    • REST
    • GraphQL
    • Security
  • SFerrand.Common (new tab)

    .NET helpers extracted from production services. Log-safe masking of sensitive data (secrets, URIs, cards, IBAN, French NIR, SIREN, SIRET), redaction in free text, check digits (Luhn, IBAN, RIB), constant-time comparison and case conversions.

    • C#
    • .NET 8+
    • Logging
    • GDPR

Training calculations

Taken from the Allure+ calculators and rewritten in C#, with their tests.

  • Sport Metrics (new tab)

    TSS, TRIMP, fitness (CTL, ATL, TSB), GPX tracks and triathlon race plans.

    • C#
    • .NET 10
    • GPX
  • Cycling Physics (new tab)

    Cycling speed from power, gradient, wind and altitude (numerical solver), plus gear calculations.

    • C#
    • .NET 10
    • Physics
  • Swim Metrics (new tab)

    Critical swim speed (CSS) from three protocols, in metres or yards, with SWOLF, Stroke Index and pace zones.

    • C#
    • .NET 10
    • Swimming
  • Running Performance (new tab)

    VMA and VO₂max from field tests (Cooper, Léger-Bouchard, Vaussenat…), race time prediction (Riegel) and running zones.

    • C#
    • .NET 10
    • Physiology
  • Training Zones (new tab)

    Heart rate zones (Karvonen), FTP estimated from the protocol and level, Coggan power zones.

    • C#
    • .NET 10
    • Power
  • HRV Recovery (new tab)

    Recovery from HRV: personal baseline by median, score, status and safeguards against noisy readings.

    • C#
    • .NET 10
    • Robust statistics

Tools

Two small command-line tools.

  • Responsive Images (new tab)

    Generates the srcset sizes (JPEG and WebP) of a photo, with a JSON manifest for the site.

    • Node.js
    • sharp
    • WebP
  • Chord Transposer (new tab)

    Transposes chords, lines and grids, and converts horn parts to F. Dependency-free JavaScript.

    • JavaScript
    • Music

Lessons learned

Case studies

The context, the choices and the current status.

Porting Allure+ from iOS to Android

Allure+ started as an iOS app written in SwiftUI, and is now published on the App Store. The Android port lives in a separate repository, and the iOS code is never modified to make it possible. iOS remains the reference: the behaviour must be the same on both platforms.

allureplus.app (new tab)

Challenge

The iOS domain (calculators, plan and workout generators) keeps changing during the port. It must be carried over faithfully, without chasing a moving target.

Architecture choices

  • Shared domain, native interfaceKotlin Multiplatform for the domain (shared module), SwiftUI on iOS, Jetpack Compose and Material 3 on Android.
  • Parity checked by testsSwift is the reference, and I rewrite it in Kotlin. Each test reuses the same input / output pairs as its Swift counterpart: more than 800 tests, on the JVM, without an emulator.
  • Calculators first, plans laterThe sequence was revised along the way: the Training tab became essential for the first release.
  • A simple screen architectureMVVM: a pure, testable computation, a StateFlow ViewModel, a Compose screen. A missing translation fails the build.
  • Local persistenceSQLDelight for history, workouts and plans, DataStore for the profile. Dependency injection by hand while the graph stays small.
  • System services behind interfacesHealth Connect, location, OpenWeatherMap weather, reminders with WorkManager. Health Connect provides RMSSD where HealthKit gives SDNN: the difference is documented.
  • No account, no backendiCloud sync and Sign in with Apple have no equivalent, and the two platforms do not sync with each other.
  • Exports and subscriptionText, calendar (ICS), FIT for watches, intervals.icu. Premium stays behind a “coming soon” screen until Google Play Billing.

Calculators, reference tools, profile, onboarding and the Training tab are ported (plans, calendar, reminders, exports). Remaining: Google Play Billing and publication.