A keyboard your users cannot tell from the system one.
PressboardKit is a keyboard engine for iOS in Swift 6. Its defaults are the system keyboard's own behaviour, down to the feel of a keypress, so parity is what you get before you configure anything.
Free — licensed per registered application, not open source.
Swift 6 · iOS 26 · Swift Package Manager · no external dependencies
A sketch of the keyboard: a suggestion bar showing the typed word, a highlighted correction and an alternative; four rows of keys; and a long-press callout open above the C key, with the plain letter selected in the middle and accented variants either side.
Why keyboards are hard to get right
A custom keyboard on iOS is not a view inside your app. It is a separate process that the system starts on demand, on a fraction of an app's memory, and it never sees the text it is editing beyond a narrow window around the cursor.
Everything a person expects from a keyboard has to be rebuilt inside that process, and the bar is unforgiving, because your users type on the system keyboard all day. A key a shade too narrow, an animation a frame late, a callout that opens on the wrong side — each one is felt before it is noticed, and a keyboard that feels wrong gets switched off.
Matching it is not a weekend of styling. It is measurement, on real hardware, behaviour by behaviour, and then keeping the match as the platform moves. That is the work this engine has already done.
What PressboardKit gives you
A rendering and text-logic engine that starts at parity, exposes every decision as a parameter, and stays inside the budget an extension is given.
Native parity by default
The default style reproduces the system keyboard rather than a house style, in light and dark: the pop above a pressed key, the long-press callouts, the press highlight, the system key click and the haptic all behave the way your users already expect. Parity is versioned, so when the platform next redraws its keyboard the new look lands beside the old one instead of replacing it under your users.
Everything is a parameter
Every behaviour is one of 51 properties on a single injected behaviour value, and every default is what iOS does. Auto-correction, the double-space full stop, caps lock, punctuation spacing, key animations — each can be turned off without touching the engine, which means the people who license the SDK from you can turn them off too.
Built for the extension budget
A keyboard extension is the tightest process on the phone, and it is killed rather than warned when it overruns. The engine pulls in no external packages at any depth, autocomplete and the emoji panel are separate modules you opt into, and an ordinary keystroke does not redraw the keys at all.
Get started
One package line, one view
The engine is a SwiftUI render view plus pure text-logic helpers. Your UIInputViewControllerowns the text document and wires the two together; the theme, toolbar, suggestion source and settings are all injected, and the kit never imports anything from your app.
.package(url: "https://github.com/PressboardKit/PressboardKit.git", branch: "main")import PressboardKit
import PressboardKitLayouts
let layout = StandardLayoutResolver.layout(for: context) // context: KeyboardContext
PressboardKeyboardView(
layout: layout,
style: MyStyleProvider(), // your theme; defaults to NativeKeyboardStyle()
behavior: .standard, // native defaults; flip any toggle to opt out
onAction: handle // route .character / .backspace / .shift / …
)Why choose it
- Typing latency
- The keys are kept off the per-keystroke render path, characters can commit on press rather than on release, and overlapping presses from two thumbs commit in the order they were actually made rather than the order they were delivered.
- Privacy
- Nothing anyone types leaves the device. Corrections come from the system spell checker and a bundled word list, both on the phone, and anything learned while typing is handed to your app to store, never to us. The engine opens no connection of its own today, and licence validation, when it arrives, will carry a licence key rather than anything typed.
- Languages
- The engine carries 73 locales, five key arrangements including Dvorak and Colemak, per-locale long-press callouts, and a domain key that offers the top-level domain of every enabled language.
- Feel
- Parity is checked side by side against the native keyboard on the same device in both themes, and touch behaviour is proved in a real keyboard extension rather than in a preview that runs inside the host app.
Languages
The engine models 73 locales. A language is a data table — its letter rows, its long-press callouts, its top-level domain — so adding one is an addition to the layout module rather than a change to the engine, and a keyboard with several languages enabled treats all of them as live at once when it decides whether a word needs correcting.
Questions
Which iOS and Swift versions does it need?
How much memory does it use?
Can I theme it?
KeyboardStyleProvider lets you repaint as much or as little as you want, and a single ThemePalette recolours the whole keyboard — keys, text, callouts, key-pop and the suggestion bar. Six themes ship built in, including the native one, which keeps the translucent system backdrop.