Most people will first encounter FINN as an app, which makes one of our earliest technology decisions sound fairly ordinary: we chose Swift to build our first mobile version of FINN.
iPhone app. Apple language. Obvious choice.
Except that wasn’t really the decision we were making.
FINN is a marine intelligence engine. We’re building it to bring together information about the boat, the voyage, the surrounding environment and the people aboard, then help captains and crews understand what matters in their particular situation.
A chart can tell us where the boat is, weather data can tell us what’s approaching, and sensors can tell us how the boat is moving. Over time, observations can begin to tell us something more specific: how this particular boat actually behaves.
But none of those sources is the intelligence engine by itself. What interests us is what becomes possible when FINN can understand the relationships among them.
That creates a technology problem very different from simply building an app. FINN may begin on a phone, but we expect its intelligence to eventually operate across phones, tablets, computers, cloud infrastructure and computing aboard the vessel itself. More importantly, several of those systems—and several people aboard—may be participating in FINN at the same time.
So the question we actually needed to answer was broader:
How do we build FINN once without requiring every place FINN appears to be the same?
That question led us to Swift, but not before trying—and seriously considering—some very good alternatives.
What our first prototype taught us
FINN didn’t begin with Swift.
Our first working proof of concept was an onboard appliance built around a Raspberry Pi and dedicated display. A deterministic backend processed vessel state, calculations, rules and insights, while a React and TypeScript interface gave us a way to interact with the system. We didn’t just prototype that architecture on a development computer; we ran it on the actual hardware.
It taught us a lot.
React worked well as an interface to FINN. What we became less convinced of was that the application framework should become the architecture of FINN.
That distinction became increasingly important when we decided the phone should become FINN’s first broadly accessible platform. We could have continued down the React path with React Native, sharing substantial portions of an application between iOS and Android. We could have chosen Flutter, another mature approach to building applications for multiple platforms from a shared codebase. At the opposite extreme, we could build entirely separate native applications—Swift for Apple, Kotlin for Android—and accept the duplication.
None of those approaches is inherently wrong. They optimize for different things.
React Native and Flutter solve a real and expensive problem: developing software for multiple platforms without building everything multiple times. Modern React Native can also move shared platform-independent functionality into C++ native modules, while Flutter compiles release applications to machine code and provides mechanisms for interacting with native platform code.
Those are meaningful advantages, and we considered them. But our experience with the original appliance led us to frame the problem differently.
Instead of asking how much of the application we could reuse, we began asking:
What part of FINN do we actually want to make portable?
Our answer wasn’t the interface.
It was the intelligence underneath it.
What should actually be portable?
Underneath FINN’s interface we’re building models of the vessel, voyage and marine environment. We’re processing hydrographic information and sensor observations, developing deterministic calculations and spatial capabilities, estimating vessel state, preserving history and laying the foundations of an intelligence system that can understand relationships among all of them.
Eventually, the screen displaying an insight may be one of the least interesting parts of the process that produced it.
Those underlying capabilities need to survive whatever happens to the interface above them. That’s why we’ve adopted a somewhat different definition of cross-platform development:
The experience can belong to the platform. The intelligence belongs to FINN.
Internally, we’ve described the same principle as one FINN, multiple embodiments.
That doesn’t mean every environment needs to run identical software, or even that every FINN component needs to be written in the same language. It means the important concepts shouldn’t change depending on where FINN happens to be running.
A vessel observation should mean the same thing. A voyage should mean the same thing. What FINN has learned about a boat shouldn’t quietly diverge because one system is running aboard the vessel while another is in a crew member’s pocket or somewhere in the cloud.
That consistency becomes even more important when those systems begin working together.
One FINN can span a vessel

Our first broadly available version of FINN starts on the phone, but we don’t think of the phone as FINN’s eventual home. It’s simply a particularly useful place to begin.
The larger opportunity isn’t just moving FINN from one kind of device to another. It’s allowing several devices, potentially running very different systems and serving different people, to participate in the same FINN experience.
Imagine planning a passage on a computer at home, where a large screen, keyboard and mouse make detailed planning comfortable. That plan follows the captain and crew aboard. Phones can provide mobility and sensing, while a tablet provides more room for charts, environmental context and information at the helm. A dedicated onboard computer can eventually process vessel and sensor data continuously, while cloud services synchronize the information that should follow the vessel and its people between them.
And this doesn’t have to be a one-person, one-device relationship.
A vessel may eventually have multiple active instances of FINN serving different roles at the same time. The captain might use a tablet at the helm while a crew member carries a phone elsewhere aboard. Another crew member might need information relevant to a different responsibility, while an onboard system continues processing vessel and environmental data in the background.
Those instances don’t need identical interfaces, capabilities or permissions. What matters is that they’re participating in the same understanding of the vessel and voyage.
A course change shouldn’t become a different voyage because it was entered from another device. An observation made by one instance of FINN should retain its meaning when it becomes relevant to another. What FINN has learned about the vessel should belong to the vessel’s evolving context, not be trapped inside whichever screen happened to collect it.
Over time, that creates room for role-aware experiences. A captain, navigator or crew member may need different information at different moments. The goal isn’t to put every piece of information on every screen, but to make the appropriate information available to the appropriate person while keeping those experiences grounded in the same underlying FINN.
That’s what one FINN, multiple embodiments means to us.
We don’t necessarily need the same application everywhere. We need FINN to work everywhere it belongs.
Where abstractions begin to matter

The individual platforms still matter because we want to use each of them well.
If a phone is going to act as an observation source aboard a boat, we want access to the capabilities of that phone rather than only the subset that happens to look identical across platforms. On an iPhone, that means direct access to Apple’s location and motion systems, background behavior, local persistence and other native capabilities. A future Android implementation should be equally free to take advantage of what Android does well.
The same principle applies to presentation. A tablet has room for a different helm experience than a phone, while a computer can provide a richer planning workspace. We don’t need to force those experiences into a lowest-common-denominator interface merely to call FINN cross-platform.
Meanwhile, beneath those interfaces we’re already building substantial marine technology. Our work with the IHO S-100 family of marine-data standards is a good example.
FINN’s S-100 implementation isn’t simply code for drawing a chart on a particular screen. We’re building it as a separate Swift package responsible for substantial marine-data decoding, semantics, spatial processing and portrayal. Behind boundaries we control, it already works with technologies written in other languages, including C components, Lua and GEOS-based spatial processing.
There is nothing about that technology that makes it impossible to use with React Native or Flutter. Both provide mechanisms for integrating native code, and modern React Native in particular has made substantial improvements to that boundary.
Our concern is therefore not whether those frameworks can accommodate FINN’s requirements. It’s what happens as more of the difficult work moves through or beneath that boundary.
A conventional cross-platform application may spend much of its life in the shared application layer and occasionally reach into native functionality. FINN is likely to spend an unusual amount of its life close to sensors, spatial processing, native libraries, background execution, marine electronics and operating-system services. As that proportion grows, some of the simplicity that made the higher-level abstraction attractive begins moving elsewhere in the architecture.
We therefore decided not to make the application framework FINN’s primary portability boundary. Instead, we put that boundary around the information FINN understands.
An iPhone and an Android phone don’t need to acquire an observation in exactly the same way. A phone and an NMEA instrument certainly don’t. What matters is that FINN can normalize those inputs into observations it understands while preserving important information about their source, quality and confidence.
Different sources can take very different paths into the system while still describing the same underlying reality.
We abstract meaning, rather than forcing every source to expose the same capabilities.
Swift beyond Apple
This is where Swift becomes more interesting than its reputation as Apple’s programming language might suggest.
Swift now officially supports Linux and Windows, and Swift 6.3 introduced the first official Swift SDK for Android. More important for FINN is how some of that portability works.
Swift code on Android compiles directly to native machine code. The Swift Android team describes its execution characteristics as similar to C and C++ built using Android’s Native Development Kit. Swift still needs interoperability when accessing Android APIs exposed through Java and Kotlin, so this isn’t a magical elimination of platform boundaries. But portable Swift code doesn’t need to become JavaScript, Dart or Kotlin simply to execute on an Android device.
Linux presents another interesting path. Swift can compile natively for x86-64 and ARM64 Linux, and its Static Linux SDK can produce fully statically linked executables with minimal external dependencies.
For ordinary application development, that may sound like an obscure technical detail. For a marine intelligence system, it isn’t. Small ARM-based Linux computers are exactly the kind of inexpensive, capable hardware that can live aboard a boat, giving us a plausible path from mobile devices toward onboard computing without assuming that important FINN algorithms need to be rewritten at every step.
There are important qualifications. We’re not claiming that every Swift package we’ve written today will compile unchanged on every one of those platforms tomorrow. Dependencies have to support each target, platform-specific capabilities still require platform-specific code, and some of these technologies are continuing to mature.
Nor does every component surrounding FINN need to be written in Swift. A cloud service, web interface, native operating-system integration or specialized hardware component should use technology appropriate to its job. FINN already integrates components written in several languages behind boundaries we control.
What interests us about Swift is the amount of core FINN capability that may be able to remain one compiled implementation as it moves among very different classes of hardware.
Portability doesn’t require technological uniformity. It requires stable boundaries.
A cross-platform application architecture can begin with a shared application and reach down into native capabilities when necessary. We’re approaching the problem from the other direction: keep FINN’s portable intelligence as close to native execution as practical, then reach outward to Apple, Android, Linux, cloud services or marine hardware where specialized capabilities are actually required.
Instead of making the application portable and reaching down when we need native capabilities, we’re making FINN portable and reaching out when we need platform-specific capabilities.
How we’ll know whether we were right

It’s tempting to turn native compilation into a sweeping performance claim. We’re not going to.
Flutter’s release applications also compile to machine code on native targets. Modern React Native has substantially improved communication between JavaScript and native code, and demanding shared functionality can be implemented in C++. “Swift is faster” would therefore be both too simplistic and, without measuring our actual workloads, unsupported.
Our hypothesis is more specific. If FINN can keep more of its core processing in one compiled implementation across different environments, we may see advantages in latency, sustained CPU utilization, memory consumption, startup behavior, thermal load and energy use while also reducing the architectural complexity required to achieve them.
Those are measurable questions, and the benchmarks that matter to us look different from many conventional application tests.
We care about what happens while FINN processes observations continuously over a six-hour passage, how much energy location and motion processing consumes, and how quickly vessel state responds when several observations arrive together. We want to understand what S-100 processing costs in CPU time and memory, how the same workload behaves on a phone compared with an ARM-based onboard computer, and what happens when chart information, vessel observations and environmental conditions are evaluated simultaneously.
Eventually, we want to measure the entire path from a meaningful change in the world to a useful insight for the captain and crew. Those results will tell us considerably more about our architectural choices than a synthetic test of how quickly two frameworks render the same list.
There is another kind of efficiency we care about just as much.
Suppose a complicated piece of S-100 processing has been implemented, tested and validated once. If we can take that same implementation to another processor or operating system, that may be more valuable than shaving a few milliseconds from an operation.
The alternative can mean maintaining separate implementations of the same standards-sensitive behavior and repeatedly proving that all of them mean exactly the same thing. That creates duplicated testing, additional opportunities for defects and, perhaps most importantly for an intelligence system, opportunities for the meaning of the data to quietly diverge between platforms.
So our benchmarking ultimately needs to answer two related questions: how efficiently does FINN execute, and how efficiently can we keep FINN consistent as it spreads across platforms?
We have a hypothesis. Benchmarking will give us the evidence, and when we have meaningful results, we’ll publish them.
Choosing for the FINN we haven’t built yet
All of this reflects something basic about boating: boats leave networks.
FINN cannot assume every meaningful operation can travel to a remote server and back before becoming useful. Cloud services can provide synchronization, larger-scale processing, updates and capabilities that genuinely belong there, but observations should be collectable locally, state should be derivable locally, deterministic calculations should be able to run locally, and useful intelligence should remain available when connectivity isn’t.
The cloud should make FINN better. It shouldn’t be what makes FINN work.
In a system that can span several people and devices, the cloud can help plans, vessel information, observations and voyage history move where they’re needed. But the boat shouldn’t stop understanding itself because connectivity disappears offshore. Systems aboard should continue doing the work appropriate to them locally and reconcile what needs to be synchronized when connectivity returns.
A lightly instrumented sailboat may initially give FINN little more than the capabilities of the phones carried aboard. Another vessel may provide a rich NMEA network and dedicated onboard computing. Future capabilities may make more sense running directly aboard the vessel than on either a phone or a remote server, and some may eventually need no screen at all.
We don’t know exactly where every part of FINN will ultimately run. That’s precisely why we care about these boundaries now.
The same is true of the people using it. A captain, navigator and crew member may have different responsibilities and need different information. Shared intelligence doesn’t require identical screens or identical roles. What needs to remain consistent is FINN’s understanding of the vessel, voyage, surrounding environment and the relationships among them.
This is more than cross-device synchronization. The longer-term goal is shared vessel intelligence.
Choosing Swift isn’t a one-time technology verdict. It’s an engineering hypothesis that we now get to test. Our original React-based appliance taught us about separating the interface from the intelligence. Our mobile implementation is teaching us about native sensors, mobile constraints and local operation. Future platforms and onboard hardware will test how well those ideas travel.
Where the architecture works, we’ll extend it. Where it doesn’t, we’ll change it. We’re not interested in defending a programming language; we’re interested in building the right architecture for FINN.
There are easier ways to maximize code reuse between mobile applications, and there are very good reasons other development teams choose them. We’re optimizing for something different.
FINN isn’t an app that happens to know about boats. We’re building a marine intelligence engine that may ultimately live in several places at once while maintaining a coherent understanding of what’s happening aboard.
The hardware will change. The interfaces will change. The available sensors and technology will change. FINN shouldn’t have to become a different intelligence system every time they do.
Our objective isn’t to write one app and run it everywhere.
It’s to:
Build the intelligence once. Deliver it appropriately everywhere.
That’s why FINN chose Swift.
