Selected work · 2026
Exail · FLS & SAMS
Defense · Naval sonar for Naval Group — mine warfare & SAS visualisation
Context
Software delivered to Naval Group through Exail — two parallel programmes on the naval sonar stack:
- FLS — mine-warfare chain: streaming sensor data, live operator displays, tight milestones.
- SAMS — SAS visualisation: legacy front-end modernisation with the project and tech leads.
This is not a startup pace. Quality gates are contractual: SonarQube thresholds, test coverage, security remediation, and release evidence are written into the delivery contract with Naval Group. Regressions are costly; compliance is part of shipping.
FLS — Industrialisation
The defining thread of my engagement was industrialising FLS — turning a critical but process-light programme into something that could deliver reliably under contract.
I contributed heavily across the full chain:
- Development process
Branching model, review rules, definition of done tied to quality gates.
- Project process
Backlog structured into Epics and stories, sprint rhythm, QA and release discipline.
- Product definition
Clarified scope with leads, translated operator needs into shippable increments.
- Process automation
Automated repetitive checks, release steps, and reporting — less manual toil before each milestone.
- CI / CD
Jenkins and Bitbucket pipeline from zero: build, test, SonarQube analysis on every merge.
- Code QA
SonarQube stood up and enforced; anomaly triage workflow; security hotspot remediation.
FLS — Quality & contractual compliance
When I joined, quality tooling was largely absent: coverage around ~20%, no SonarQube, ~800 open anomalies and 16 security hotspots.
Measurable outcomes
- Stood up SonarQube from zero and wired it into Jenkins / Bitbucket so every merge request carries auditable quality signal.
- Burned down the anomaly backlog from ~800 to ~70 — fixing, re-scoping, or closing stale items with QA sign-off.
- Cleared every security hotspot (16 → 0) with targeted refactors and dependency updates.
- Enforced release discipline across the team of 10 so each Naval Group milestone could be defended with evidence.
Tests — FLS-IHM
On FLS-IHM, the unit suite ran on Karma / Jasmine — ~2520 specs green at the end of the modernisation epic. Coverage and SonarQube gates applied to this stack; SAMS used a different toolchain (see below).
Runtime & integration
- gRPC — extended and hardened gRPC usage inside the application for sensor and service communication; aligned protobuf contracts with the C++ back-end team.
FLS — Desktop runtime & security hardening
FLS ships as an Electron ^32 desktop application, packaged with electron-builder for Windows (NSIS) and Linux. The runtime is multi-process: the main process hosts ~12 gRPC clients and bridges to the renderer through a preload IPC layer; the product runs in Master / Slave operational mode on the mine-warfare chain.
- Electron upgrade
Raised the embedded shell from Electron 17 to 32 — closing years of platform security debt in a defence delivery context.
- Process isolation
Sandbox enabled; removed legacy
sandbox: false; settings and privileged operations routed through IPC instead of direct renderer access. - Preload bridge
contextIsolation and a hardened preload script — renderer stays untrusted; gRPC and system calls stay in main.
- Packaging
electron-builder targets for Windows NSIS and Linux — repeatable operator installs on board and ashore.
FLS — Sonar visualisation & geospatial core
This is what the operator watches — the product's real-time render layer, not background plumbing:
- OpenLayers — mission map, WMS layers, swath overlay, waypoints, coordinates in DDM.
- Three.js — 3D bathymetry for depth interpretation during triage.
- D3 — profile and swath rendering for along-track and cross-track views.
- GeoTIFF — raster ingestion with colour palettes and LUT mapping for sensor-specific contrast.
FLS — Real-time reliability
Live sonar displays fail when streams break silently — not when a single query is slow. I focused on stream resilience, not generic performance tuning:
- Fixed gRPC client leaks that accumulated under long operator sessions.
- Tamed reconnect storms under load — throttling when back-end saturation triggered "max client reached".
- Handled stale streams after reconnection so displays did not show ghost state from a prior session.
- Routed swath streaming over WebSocket where the data path required lower-latency push than polling.
FLS — Angular modernisation
The front-end was on Angular 13. I led the migration to Angular 21:
- Signals, OnPush, and generalised control flow (
@if/@for/@defer) — zoneless-ready: the change-detection gap closed;zone.jsnot yet removed from the bundle. - Store layer — dedicated signal stores for cross-screen sonar state instead of scattered RxJS subjects.
- Design system — moved the in-project component library onto the Exail group design system, aligned with the Exail brand chart, so FLS shares tokens and primitives with sister programmes.
Brand & visual identity
The Exail chart encodes the Exail group look for operator software — not the corporate marketing site, but the same DNA: cyan accent on dark chrome, Gilroy/Gotham typography, and day / twilight / night theme variants for long sonar sessions (the maritime IHM charter Exail inherited from the iXblue product line).
Typography
Display · Gilroy 600
Crafted interfaces, delivered on time
UI body · Gilroy 400
Building products that work well for the people who use them every day.
Chrome · Gotham 700
OVERVIEW · PROCESS · DELIVERY
Telemetry · Gilroy 500 · tabular nums
3 missions · 24 months · 100%
Colour
#1CEDC7
--primary · rgb(28 237 199)
Group signature cyan — active tracks, focus rings, selection and primary CTAs on operator chrome.
#00FFDA
Word-mark chevron · Exail emphasis
Brighter cyan from the Exail logotype — chart highlights and brand-forward accents in Figma.
#191919
--secondary · rgb(25 25 25)
Primary app shell — nav rails, drawer frames and persistent operator chrome.
#131313
--tertiary · rgb(19 19 19)
Night-mode canvas behind sonar tiles and dense data tables.
#2A2A2A
Cards · detail panes
Raised panels between signal view and metadata — minimal chrome, stable landmarks.
#9CA3AF
Secondary labels · de-emphasised metadata
Supporting copy, axis labels and non-critical hints on dark backgrounds.
Operational palette
#3D86D8
Cross-pane links · drill-down
Secondary interactive states — open detail without competing with primary cyan.
#FBDA26
Threshold · caution states
Anomaly callouts and threshold breaches — readable on night chrome without alarm red.
#D02222
Alarm · hotspot salience
Hard alarms and security hotspots — reserved for states that must not be missed.
#000000
Text on cyan fills
Selection chips and primary buttons keep black type for contrast on bright cyan.
#FEFEFE
Day theme · briefing mode
Light variant for planning and review sessions — same tokens, inverted surfaces.
#052D4A
Twilight theme wash
Mid-shift theme between day and night — reduced glare, cooler base than pure black.
Shape & operator density
- Themes
Day, twilight and night variants — colour ramps swap while layout landmarks stay fixed for hour-long triage.
- Motion
Restrained transitions keyed to material state — no decorative motion that breaks spatial memory.
- Density
Keyboard-first flows, disciplined table hierarchy, minimal chrome between signal and detail panes.
The modernisation program
The Angular and platform migration was not a single risky cutover. I structured it as a delivered transformation program under an umbrella epic — seven workstreams, each leaving the product buildable and CI-green before the next step.
- E1 — Foundations
Angular 13 → 21 LTS by incremental steps; Node 20+; builder migration browser → application (esbuild); Electron 17 → 32; standalone bootstrap.
- E2 — Renderer architecture
Signals · OnPush · Standalone · Control Flow (@if / @for / @defer) · zoneless-ready.
- E3 — gRPC renderer layer
Domain facades with signal stores — one coherent layer between protobuf services and operator screens.
- E4 — UI migration
Deprecated @ix-components web components → PrimeNG + Exail charter — shipped with zero ix-component tags and zero @ix-components packages.
- E5 — Shared Web UI + Storybook
Mutualised component library (Exail design system on PrimeNG 21 + charter preset), adopted by both FLS-IHM and SAMS — one design system across sonar IHMs, end of duplicated UI between programmes.
- E6 — CI/CD & delivery
Jenkins: PR and tagged releases, Bitbucket integration, quality gates on every merge.
- E7 — Quality, tests & SonarQube
Contractual coverage and anomaly burn-down; FLS Karma/Jasmine suite and SAMS Playwright + Vitest per programme.
SAMS — Front-end architecture rebuild
On the SAS visualisation axis, I rebuilt the front-end architecture from scratch with the project and tech leads — not a surface refresh on legacy patterns.
- NgRx SignalStore — one store per sensor domain: GPS, INS, CTD, POD, XTF, sonar, sync, survey, network, offsets, terminal, altitude.
- Real-time WebSocket bridges — live sensor feeds wired into store updates without scattered subscription logic.
- Global search — cross-entity lookup across the survey perimeter.
- ApiClient + contracts / mappers — typed boundaries between back-end payloads and UI state.
- Lazy routes and a toast interceptor — load only what the operator needs; consistent feedback on API failures.
I also authored the Exail design-system chart in Figma. Test coverage on the targeted perimeter moved from ~0% to ~95% as a consequence of the rebuild — Playwright (e2e) + Vitest on SAMS-150-UI, distinct from FLS-IHM's Karma/Jasmine stack.
Cross-project knowledge & shared services
FLS and SAMS share gRPC contracts, service boundaries, and operator patterns — but without structure, each programme rediscovered them independently. I set up a versioned Obsidian vault (integrated as a git submodule) organised by domain:
_contract— protobuf and API contracts capitalised once, referenced from both codebases._architecture— system diagrams and decision records, with generated architecture tables._domain— mine-warfare and SAS business rules in operator language.
This pairs with the Shared Web UI workstream (E5): mutualised UI components, mutualised knowledge, mutualised services — one engineering surface across sonar IHMs instead of two siloed programmes.
AI-augmented engineering
Inside a defence delivery context — contractual quality bars, classified constraints, no room for unreviewed generated code — I treated AI as industrial tooling, not a shortcut. I drove this track solo while the wider programme ran in parallel:
- AI development agents — trained colleagues on when to use them, what to verify, and how to keep human sign-off on contract-bound changes.
- Workflow integration — code review assistance, test generation, migration refactors, documentation and knowledge-base upkeep in the Obsidian vault.
- Release enablement for the team — in parallel, helped the other developers stay on human release rhythm: clearer organisation, milestone preparation, and delivery discipline so Naval Group gates did not slip.
Constraints
Incident response happens in hour-long bursts; interfaces must preserve spatial memory and tolerate keyboard-first flows.
Long sessions break when the UI forces re-discovery — keep landmarks stable and motion honest.
Interface
Dense tables stayed readable via disciplined hierarchy, restrained motion keyed to material state transitions, and minimal chrome between signal and detail panes.
Impact
Naval Group receives evidence-backed releases instead of best-effort drops. Operators hold context through long triage windows. Engineering runs on industrialised rails — CI, QA, Electron-hardened desktop delivery, and a modern front-end stack that can absorb the next Angular train without another multi-year cliff.
Fullstack Engineer · Freelance