Skip to content
PressboardKit

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 52 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.

73
locales the engine models
52
behaviour toggles, all defaulting to native
522
tests green in the simulator suite
0
external package dependencies, at any depth

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.

Read the integration guide

Package.swift
.package(url: "https://github.com/PressboardKit/PressboardKit.git", branch: "main")
KeyboardViewController.swift
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.

See the language and layout support

Questions

Which iOS and Swift versions does it need?
iOS 26 or later and Swift 6. It is distributed as a Swift package, and it is iOS only — there is no Mac or visionOS build.
How much memory does it use?
A keyboard extension is a separate process on a much tighter memory budget than an app, and the engine is built to live inside it with room to spare. It pulls in no external packages, and autocomplete and the emoji panel live in their own modules so a keyboard that does not need them never loads them.
Can I theme it?
Yes. 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.
Does it work offline? Does it send anything anywhere?
Typing works entirely offline, and nothing anyone types is sent anywhere. Spelling and corrections come from the system checker on the device, falling back to a bundled word list where the system has no data for a language, and learned word pairs are passed to your app to persist however you choose. The engine contains no networking code today; licence validation is planned and will run in the containing app, carrying a licence key rather than text.
Which languages are supported?
73 locales are modelled, with layout tables, long-press callouts and correction rules resolved per locale. Adding a language is a data table rather than a change to the engine, and the correction layer judges a typing slip against the arrangement actually on screen, so a QWERTZ keyboard treats QWERTZ neighbours as neighbours.
How is it licensed?
Free. There is no charge for a licence and no tier above it — a registered application gets the whole engine. It is licensed rather than open, though: you register an application by product name and bundle identifier, and we issue a licence against it. Register an application and a licence is issued straight away. Validation works the way KeyboardKit's does, with the SDK checking the licence at setup; that check is not shipped yet. Terms are on the access page.

Ship a keyboard that feels like the one already on the phone.