Dev48
ЯЗЫК
  • О нас
  • Услуги
  • Индустрии
  • Технологии
  • Статьи
  • Контакты
Забронировать звонок
    Главная/Статьи/Kak pyat veb razrabotchikov sozdali rasshirenie klaviatury dlya ios s pomoschyu
Dev48
info@dev48.org+375 29 320-40-96WhatsApp@isky_by

© 2026 · Все права защищены.

Как пять веб-разработчиков создали расширение клавиатуры для iOS с помощью Expo

Источник: Expo Blog•11 ноября 2026 г. в 15:14

Как пять веб-разработчиков создали расширение клавиатуры для iOS с помощью Expo

Пять веб-разработчиков Supernova управляют тремя приложениями Expo, включая Superflow — голосовую клавиатуру с расширением для iOS на Swift объемом 17 000 строк.

Это гостевой пост от Анирудха Кунтура, сооснователя и технического директора Supernova, написанный совместно с Шубхом Порвалом и Саи Васудаттой. Компания Supernova базируется в Бангалоре и создает потребительские приложения для людей, которые учатся и работают на английском языке.

Флорист в небольшом городке на юге Индии получает запросы в WhatsApp от клиентов, которые ожидают безупречного английского. Он говорит на телугу. С помощью Superflow он надиктовывает текст на телугу в клавиатуру и отправляет грамотный ответ на английском.

Superflow — одно из трех приложений, которые создает и поддерживает наша команда в Supernova. На iOS расширение клавиатуры занимает около 17 000 строк кода на Swift, и оно находится в том же проекте Expo, что и остальная часть приложения. Мы используем Continuous Native Generation (CNG) для генерации нативных проектов, а сборку и доставку осуществляем с помощью Expo.

Нас пять разработчиков, и до Superflow никто из нас не писал нативный код для iOS или Android. Первые черновики написали ИИ-агенты, а телеметрия с реальных телефонов подсказала нам, что нужно исправить. Нам ни разу не пришлось покидать экосистему Expo для этого. В этом посте рассказывается о том, как мы запускаем три приложения из одной кодовой базы, как мы переходим к нативному коду там, где этого требует продукт, и как мы сделали этот код надежным.

Как мы к этому пришли

Мы начинали как образовательная компания, создавая онлайн-классы и викторины в вебе. Когда вышла GPT-4, мы создали прототип разговорного репетитора английского языка и захотели перенести его на телефоны. Мы рассматривали Flutter, а также использование Capacitor или Ionic для обертки web view. Мы выбрали React Native и Expo, потому что уже ежедневно работали с TypeScript и React. На тот момент я был практически единственным разработчиком.

Этот репетитор превратился в приложение Supernova. У него около 26 миллионов загрузок и 3,5 миллиона активных пользователей в месяц. Оно входит в топ-10 приложений в Google Play в Индии и занимало первое место в категории «Образование» в App Store в Индии.

Мы думали, что со временем перерастем Expo. Спустя 26 миллионов загрузок и три приложения мы все еще ждем этого момента.

Вся кодовая база теперь на TypeScript: React Native для приложений, React для веба и Node для бэкенда, развернутого в основном в serverless-среде на Vercel и Cloudflare. Все в команде — фулстек-разработчики. Никто не закреплен за конкретным приложением: тот, кто берет задачу, работает с любой частью системы, которой она касается.

Каждое новое приложение начинается с того, что было создано для предыдущего

Создание Supernova научило нас тому, какие компоненты необходимы любому потребительскому приложению в Индии, и мы создали каждый из них один раз. Они находятся в общих пакетах в нашем монорепозитории, управляемом с помощью Bun workspaces и Turborepo, и каждое новое приложение начинается с них.

  • Вход: автозаполнение номера телефона, верификация Truecaller в одно касание и SNA через операторов связи. Большинство пользователей никогда не вводят свой номер вручную.
  • Платежи: UPI и шлюзы, которые работают для каждого приложения «из коробки», плюс RevenueCat для биллинга в App Store и Play, оформление заказа в одно касание, подписки, пробные периоды и счета.
  • Уведомления и вовлечение: пуш-уведомления, кампании по повторному вовлечению и напоминания.
  • Мониторинг ошибок и телеметрия: Sentry для сбоев, а также наша собственная структурированная телеметрия (подробнее об этом ниже).
  • Плагины конфигурации: каждый нативный SDK (Razorpay, Singular и другие) настраивается через плагин конфигурации в общем пакете, поэтому для нового приложения достаточно добавить одну строку в конфиг вместо редактирования нативных проектов.
  • Формы онбординга, управляемые сервером, наш UI-кит и система экспериментов.
  • Обновления «по воздуху» с помощью Expo Updates.

Superflow получил все это в первый же день, поэтому нам оставалось создать только то, что было новым. Мы разрабатывали Superflow около трех месяцев, и его годовая выручка уже достигла 1 миллиона долларов. Наше третье приложение, Sonic, — это ИИ-ассистент для звонков, который отвечает на спам и звонки курьеров за вас.

Superflow начинался как обходной путь с копированием и вставкой

Большинство учащихся Supernova — работающие специалисты. Они хотят уверенно говорить по-английски для продвижения по службе или собеседования. Та же проблема проявилась и в письме. На работе большая часть общения должна происходить на английском, и печатать на нем так же сложно, как и говорить. Их обходным путем было объяснить ChatGPT, что они имели в виду, а затем скопировать ответ в WhatsApp или электронную почту. Superflow устраняет этот шаг. Вы говорите на родном языке и получаете безупречный английский прямо в поле ввода.

Добавление второго приложения все равно потребовало серьезной работы, в основном на бэкенде. Теперь каждый запрос содержит ID приложения. Пользователи, подписки, платежи, эксперименты и пуш-токены привязаны к конкретному приложению, поэтому оплата Supernova не открывает доступ к Superflow, и каждое приложение получает свой бесплатный пробный период. Учетные данные для пуш-уведомлений, ключи биллинга магазинов, шаблоны OTP, а также конфигурации главной страницы и обновлений также индивидуальны для каждого приложения.

На стороне клиента работы было немного. Каждое приложение регистрирует ID, и общая оболочка выбирает на его основе тему, навигатор и конфигурацию. Навигатор Superflow повторно использует общие экраны, такие как вход, платежи и профиль, и добавляет свои собственные для диктовки, словаря и разрешений.

Части, которые должны были быть нативными: клавиатура iOS и виджет Android

Большая часть Superflow — это одно и то же приложение на React Native для обеих платформ. Часть, которой люди пользуются весь день, — это то, что находится поверх других приложений: кастомная клавиатура на iOS и плавающий пузырек на Android. Они должны были быть нативными. На Android пузырек представляет собой оверлей-виджет плюс службу специальных возможностей.

Клавиатура iOS — это полноценный движок клавиатуры с функцией диктовки. Только клавиатура занимает около 17 000 строк на Swift. В сумме для iOS и Android в Superflow около 68 000 строк нативного кода, плюс еще 36 000 строк нативных тестов.

Расширение клавиатуры также работает по более строгим правилам, чем обычное приложение. Оно запускается в отдельном процессе с небольшим лимитом памяти, и iOS завершает его без предупреждения при превышении этого лимита. Оно не может выходить в сеть или обмениваться данными с приложением, пока пользователь не включит «Полный доступ». Оно видит только текст вокруг курсора. И оно не может использовать микрофон, что неудобно для голосовой клавиатуры.

Поэтому запись ведет само приложение. Когда вы нажимаете на микрофон, клавиатура просит Superflow начать работу. Если приложение запущено в фоновом режиме, запись начинается немедленно. Если нет, клавиатура открывает его, и оно возвращает вас прямо туда, где вы печатали. Написанный нами модуль Expo отвечает за запись, Live Activity во время разговора и обмен сообщениями между клавиатурой и приложением через общую App Group. Сторона React Native берет на себя все остальное: авторизацию, транскрибацию, историю и повторные попытки.

Добавление самого расширения требует всего одного конфигурационного файла благодаря плагину @bacons/apple-targets от Эвана Бэкона:

Наши собственные плагины конфигурации настраивают остальные нативные зависимости, включая провайдеров входа по OTP, платежные SDK и Truecaller. CNG генерирует нативные проекты на основе этой конфигурации, поэтому Superflow использует ту же настройку, что и другие наши приложения, включая обновления «по воздуху» для JavaScript-частей. Спросите Шубха Порвала, AI-инженера в Supernova, что самое лучшее сделала для нас Expo, и он ответит «CNG» еще до того, как вы закончите вопрос.

Виджеты, Live Activity, которую вы видите во время диктовки, и поддержка локальной LLM от Apple — все это появилось таким же образом: новая папка со Swift-кодом, несколько строк конфигурации и никакого проекта Xcode, за которым нужно следить.

Нам никогда не приходилось отказываться от Expo, чтобы достичь этого. Когда нам требовалось что-то, чего Expo не умеет — например, расширение клавиатуры, плавающий виджет или служба специальных возможностей — мы писали это на нативном коде и подключали как Expo module или config plugin. Остальная часть приложения оставалась прежней. Теперь, когда агенты могут писать на Swift и Kotlin, некоторые утверждают, что стоит пропустить React Native и полностью перейти на натив. Для нас это означало бы создание и тестирование каждого экрана входа, пейволла и процесса онбординга дважды. С Expo мы создаем функцию один раз и тестируем ее на одной платформе, а для общего UI мы уверены, что она будет работать и на другой. Мы пишем нативный код только там, где этого требует продукт. Выбор Expo не лишил нас никаких нативных возможностей.

Как клавиатура стала хорошей: агенты, телеметрия и частые релизы

Агенты быстро подготовили первые рабочие версии. Понять, работают ли они на реальных телефонах, было сложнее, потому что клавиатура или плавающий виджет выходят из строя незаметно. Android убивает службу для экономии заряда батареи, настройки производителя телефона отзывают разрешение или текст просто не попадает в WhatsApp. Ничто из этого не отображается как сбой (crash).

До запуска Expo Observe мы встроили телеметрию в нативный код, чтобы получить ответы на важные для нас вопросы:

  • Появился ли виджет? Мы логируем, когда «пузырек» прикрепляется к экрану, когда его окно закрывается, пока служба еще жива, и когда отозванное разрешение блокирует его, а также отправляем сигнал «heartbeat». Каждое событие содержит состояние разрешений, состояние батареи и режима энергосбережения, объем памяти, тепловое состояние, сеть и последнюю причину завершения процесса операционной системой (ANR, сбой, нехватка памяти).
  • Попал ли текст по назначению? Каждая авто-вставка фиксирует, подтвердили ли мы наличие текста в поле другого приложения и что это было за приложение.
  • Сработала ли диктовка? Мы отслеживаем ошибки запуска микрофона, «тихий» микрофон (сторожевой таймер прерывает запись после 15 секунд отсутствия звука), переподключения потока и задержку транскрипции. Мы также фиксируем, принял ли пользователь результат, отредактировал его или отклонил.
  • На iOS клавиатура передает запись основному приложению. Там мы логируем, какой путь запуска был использован, сколько времени занял запуск и состояние аудиосессии в случае неудачи.

События проходят через один модуль телеметрии с одинаковым API на TypeScript, Swift и Kotlin. Они ставятся в очередь в outbox на устройстве, поэтому ничего не теряется при завершении процесса. Клавиатура записывает свои события в общую App Group, а приложение загружает их. Наш бэкенд пересылает все в Axiom, а ошибки уходят в Sentry.

Вот что это помогло обнаружить. У некоторых пользователей наш первый виджет для Android просто исчезал, и в отчетах о сбоях ничего не появлялось. Данные heartbeat показали, что у этого было несколько отдельных причин. На некоторых телефонах виджет не возвращался после выключения экрана, что затронуло около 1 700 пользователей. На Android 12 и более поздних версиях ОС отказывалась перезапускать нашу службу из фонового режима, что затрагивало около 2 500 пользователей в неделю.

Самый сложный случай для обнаружения: настройки Android показывали, что наша служба специальных возможностей включена, но после повторяющихся сбоев ОС незаметно прекращала ее работу. Никаких ошибок не возникало, и виджет просто не появлялся. Единственный способ поймать это — сравнить флаг в настройках с тем, запущена ли служба на самом деле. Теперь мы проверяем это каждые 15 минут. Когда данные расходятся, мы логируем это и отправляем пользователю уведомление о необходимости снова включить службу.

Бэкенд также реагирует на эти данные. Когда heartbeat виджета молчит в течение часа, задание отправляет бесшумный push-сигнал, который перезапускает его. Подтверждения вставки показали нам, каким приложениям требуются запасные варианты (fallbacks).

Каждое исправление доставлялось одинаково. Исправления JavaScript выходят как OTA-обновление (over-the-air). Нативные изменения проходят через сборку, инициируемую тегом в Expo Workflows, а Fingerprint сообщает нам, к какому типу относится изменение. Тесты на каждом PR (435 на Swift, около 1 650 на Kotlin) отлавливают регрессии в нативном коде, и мы сравниваем показатели сбоев и ANR в Play Console между сборками перед дальнейшим развертыванием.

Агенты также проверяют свою работу. С помощью agent-device агент управляет симулятором, проходит по изменениям и делает скриншоты. Сначала мы использовали это для тестирования телеметрии во всех трех приложениях, а теперь используем для клавиатуры и виджета.

Open source

Несколько вещей, которые мы создали, теперь находятся в открытом доступе: expo-phone-number-hint для автозаполнения номера SIM-карты при входе, expo-truecaller для верификации в одно касание и expo-ruler, который переносит Ruler от Spotify в Expo, чтобы вы могли видеть, что занимает место в вашем Android-приложении.

Ruler — это то, как мы уменьшили размер загрузки Supernova для Android с 63 МБ до 33 МБ. Читая отчет, Shubh заметил, что декодеры GIF и WebP из React Native все еще включены в сборку, хотя мы используем expo-image. Он отправил в апстрим Expo опцию, так что начиная с SDK 58 любое приложение может отключить их в expo-build-properties.

Если вы небольшая команда

Относитесь к своему первому приложению как к фундаменту для следующего. Общие пакеты для входа, платежей и экспериментов — вот почему запуск нашего новейшего приложения занимает около месяца.

Переходите на натив только там, где этого требует продукт. Для нас это были клавиатура и плавающий «пузырек». Все остальное осталось общим. Когда вам действительно нужен нативный код, напишите эту часть на Swift или Kotlin как Expo module. Мы сделали это без опыта нативной разработки. AI-агенты написали первые черновики, а наши тесты выявили то, что агенты упустили.

Дайте вашим агентам возможность проверять свою работу до того, как ее проверит человек. Для нас это означает управление симулятором со стороны агента, тесты на каждом PR и телеметрию с реальных телефонов.

Если вы хотите попробовать, начните с Expo Modules API.

← Все статьи

О чём эта статья

Ещё в разделе «Разработка ПО»

Все →
Правила Amazon по времени обработки заказов заставляют продавцов электронной коммерции сосредоточиться на точности данных по SKU
Descartes

Правила Amazon по времени обработки заказов заставляют продавцов электронной коммерции сосредоточиться на точности данных по SKU

Новые правила iGaming в регионе EMEA теперь требуют запросов в реальном времени
SingleStore

Новые правила iGaming в регионе EMEA теперь требуют запросов в реальном времени

Управляйте своим денежным потоком с помощью Squarespace Balance
Squarespace Commerce

Управляйте своим денежным потоком с помощью Squarespace Balance

100 самых упоминаемых брендов в ChatGPT (ноябрь 2026 г.)
Ahrefs

100 самых упоминаемых брендов в ChatGPT (ноябрь 2026 г.)

Sitecore представляет MarketingIQ для превращения аналитики бренда в рост бизнеса
Sitecore

Sitecore представляет MarketingIQ для превращения аналитики бренда в рост бизнеса

10 вопросов, которые стоит задать представителю Braze после приобретения компании Salesforce
Clevertap

10 вопросов, которые стоит задать представителю Braze после приобретения компании Salesforce

Ещё от Expo

Как ускорить итерации с помощью Expo, Supabase и ИИ
Expo

Как ускорить итерации с помощью Expo, Supabase и ИИ

Сколько инженеров нужно для создания социальной сети?
Expo

Сколько инженеров нужно для создания социальной сети?

Разбор нового слоя JNI в Expo Modules 2.0
Expo

Разбор нового слоя JNI в Expo Modules 2.0

Как один разработчик занял 2-е место в нидерландском App Store с образовательным приложением на Expo
Expo

Как один разработчик занял 2-е место в нидерландском App Store с образовательным приложением на Expo

Программа Apple Developer Program: бесплатная и платная версия
Expo

Программа Apple Developer Program: бесплатная и платная версия

Игра-головоломка про котиков на WebGPU, созданная на Expo за три дня с ИИ-агентом в роли отдела тестирования
Expo

Игра-головоломка про котиков на WebGPU, созданная на Expo за три дня с ИИ-агентом в роли отдела тестирования