Case study
Replacing a commercial keyboard SDK inside Rewordo
Rewordo is an AI rephrasing keyboard for iOS. It needed a keyboard that is indistinguishable from the system one, an AI toolbar above the keys, and all of it inside a keyboard extension's memory budget. PressboardKit exists because of those three constraints.
Rewordo · iOS
- Third-party SDKs replaced
- 1
- External dependencies
- none
- Behaviours the host can configure
- 51
Rewordo is an iOS app and keyboard extension that rephrases what you are writing with an AI model. The interesting part of the product is the toolbar above the keys. The hard part is everything below it: a full keyboard that users must not notice they are using.
That is an unusual shape for a product to be in. Rewordo’s own feature is a strip of UI and a network call. The rest of it — layouts, callouts, shift and caps lock, spacebar drag, autocorrect, the emoji panel, haptics, the pop over a pressed key — is table stakes, in the sense that getting any of it visibly wrong loses the user before they reach the feature they installed the app for. A keyboard that feels a little off is not a keyboard people leave enabled.
PressboardKit was built for that job, as a separate package with no knowledge of Rewordo at all.
Why the third-party SDK went
Rewordo originally ran on a commercial keyboard SDK. It worked, and replacing a working dependency is not something to do lightly. Three things decided it.
The first is roadmap control. A whole wave of the engine’s task list came directly from open issues against that SDK — small parity gaps, each one individually minor, collectively the difference between “a keyboard” and “the keyboard”. Fixing them meant waiting on someone else’s release cycle and someone else’s priorities.
The second is that parity work is open-ended and specific. “A single character could
be auto-corrected” — typing g and being offered a highlighted get — is the kind
of bug that turns Add 100 g of flour into Add 100 G of flour. It is not a feature
request. It is a small rule, measured against the native keyboard, that only the
party who cares most will ever get round to.
The third is that an engine you own can be sold. If the work has to be done anyway, it can be done as a product rather than as app-internal code — which is a design constraint before it is a business one, because it means the engine is not allowed to know anything about the app it was written for.
What parity had to mean
The engine’s brief is one sentence: the keyboard must look and behave exactly like the native iOS keyboard, and any deviation is a defect rather than a styling choice. In practice that means measuring rather than approximating.
Colours and proportions come off the native keyboard, read in light and dark and compared side by side on the same device. The double-space full stop has a time window because the native one does, and the window is what it measured as rather than what seemed reasonable. Exactly one punctuation key on the numeric page returns you to the letters, which we know because somebody tapped all of them. Autocorrect leans on the same system spell checker native does, including the awkward parts — it is not equally capable in every language, and a keyboard that trusts it blindly silently corrects nothing outside English.
None of this is negotiable per-app, which is precisely why it belongs in a shared engine rather than in Rewordo.
The memory ceiling
A keyboard extension gets a fraction of an app’s memory, and being over it does not degrade: iOS kills the process and the keyboard vanishes mid-sentence. The engine is built to sit inside that budget with headroom, which rules out heavy frameworks, embedded runtimes and, in general, convenience.
It also demands measurement on a device rather than reasoning from the code. One real case: memory climbed every time the keyboard was dismissed and shown again, until iOS killed the process — while typing itself, which is what everybody instruments, cost almost nothing. Nothing in the code looked wrong, and no amount of typing would have found it. Only watching a real extension across the lifecycle iOS actually puts it through did.
What the host injects
Rewordo needed the keyboard to carry its own UI and its own identity without the engine knowing what either of those is. So everything host-specific is a slot or a protocol:
- A toolbar slot above the keys, where Rewordo’s AI strip lives. The engine lays the keyboard out around it and otherwise ignores it.
buttonContent, to override the content of any key — how a host puts a language badge on the space bar, as the native keyboard does.KeyboardStyleProvider, with a native-looking implementation as the default. A host repaints only what it wants to.SuggestionProviderand the next-word predictor, so the source of suggestions is the host’s choice. Learned word pairs are handed back to the host to persist — in Rewordo’s case through the App Group it shares with its extension — because the engine has no business owning storage.KeyboardBehavior, 51 flags, every one defaulting to the native behaviour. Nothing is hardcoded on; a host that disagrees with a decision can turn it off rather than fork.
The rule that makes this hold is negative: the kit must not import anything from the
app. It does not know about Rewordo’s App Group, its theme, or its accent colour, and
it has no external package dependencies at all. A LicenseGate seam has been in the
public API from the first version as a no-op, so that turning the engine into a
licensed product later is a fill-in rather than a redesign.
Status
The engine’s functional phase is complete and covered by several hundred tests run on the simulator. Rewordo now ships on it: the integration landed behind a facade with a debug switch between the old SDK and the new engine, so the two could be compared in the same build on the same device — which, given how much of this work only reproduces in a real out-of-process extension, was the only comparison worth anything. The commercial SDK is gone from the app.