Projects
Spendly: This is a local-first AI expense tracking app I built that lets you log expenses just by taking about them. It also allow you to chat with a Large Language model(LLM) about your expenses. The idea for Spendly rose out of a personal problem - the need to track my expenses. What began as an afternoon chat with my friends in my room, is now an app on the App Store. That being said, I use Spendly basically everyday and I'm glad I built it. I learned a lot while building Spendly, e.g. I learned how to implement tool calling, Retrieval Augmented Generation, local-first functionality and so much more while building this app! I also wrote a blog post on the my experience going through the app store review process for this project. Below is the tech stack and a list of tools I used:
- App framework: Expo + React Native
- Auth and Backend(for storing expenses for RAG): Supabase with the pg-vector extension
- Chat model: gpt-oss 120b from OpenAI hosted on Groq for fast inference
- Analytics: PostHog
- Transcription model(STT): I built my own custom native module that leverages on-device transcription on iOS. On android it still does it remotely using nova-3 on Deepgram.
- Save model(for parsing the transcription and saving it to the local db): gpt-oss20b from OpenAI hosted on Groq
- Embedding model: Mistral embed from Mistral AI
- Local-DB: op-engineering/op-sqlite for storing information locally.
- ORM: Drizzle ORM (really good)
- Rate limiting: I used Upstash Redis for rate-limiting
- I used the vercel ai sdk 5 for handling requests to the LLMs
- I used Expo Application Services to automate the process of building and submitting my app to testflight and also to host my api routes where all server code resides.
- For this project, I tried alot of code editors from VsCode + Github Copliot to Cursor to Kiro and also Trae AI. I mostly used VsCode because of GitHub education, but will ultimately recommend Trae for good pricing, the apply feature, nice community, Cue and some of the best UI and Cursor for Tab and access to more mainstream providers like AWS Bedrock.
expo-speech-transcriber: A native iOS module I built to enable on-device speech transcription in React Native and Expo apps using Apple's Speech framework. I created this while building Spendly because I wanted transcription to work offline and keep user data completely private — no audio leaves the device.
The package supports both the legacy SFSpeechRecognizer API (iOS 13+) and the newer SpeechAnalyzer API (iOS 26+), though I recommend using SFSpeechRecognizer for its reliability and broader device support. It includes a config plugin that automatically handles the necessary iOS permissions, making integration seamless.
Through this project, I learned how to:
- Write native Swift code and bridge it to React Native using Expo Modules API
- Work with Apple's Speech framework and handle permission requests
- Build and publish an npm package with proper TypeScript support
- Create Expo config plugins for automatic native configuration
- Structure and document open-source libraries
The package is now published on npm and is being used in production in Spendly. It processes transcriptions completely offline while respecting user privacy.
Built with Swift, Expo Modules API, TypeScript, and runs on iOS 13+.
react-native-nitro-symbols: A high-performance library I built to bring Apple's SF Symbols into React Native with support for modern animations. I created this to access the latest iOS visual effects, specifically the
.drawOnanimation introduced in iOS 26—which weren't accessible through existing icon libraries - AFAIK.The package leverages Marc Rousavy's Nitro Modules to interface directly with native code via the JSI (JavaScript Interface), offering superior performance over the traditional bridge. To make this work, I had to use a hybrid solution that embeds declarative SwiftUI views inside React Native's imperative UIKit-based Fabric renderer using
UIHostingController.Through this project, I learned how to:
- Bridge declarative SwiftUI views into the legacy UIKit framework
- Use Nitro Modules to build native view components
- Map JavaScript strings to native Swift enums and types efficiently
- Handle iOS version availability checks for features
The library is open-source and allows developers to easily implement native iconography with rich animations like bounce, pulse, and draw. I also wrote a blog post on how I built it. The library is also available on npm
Built with Swift, SwiftUI, Nitro Modules, JSI, and runs on iOS 17+ (with advanced animations for iOS 26+).
react-native-nitro-cos-sim: A high‑performance cosine similarity module for React Native, implemented in Swift using Nitro Modules. I built this to explore how far you can push native performance for embedding‑style workloads (e.g. OpenAI vectors with length 1536) compared to a well‑optimized JavaScript baseline like the Vercel AI SDK.
The library exposes a single API to compute cosine similarity and supports both regular JS arrays and
ArrayBuffer/ typed arrays, but the real speedup comes from usingFloat64Arrayand passing the underlyingArrayBufferinto native. On the iOS side, it uses a scalar Swift implementation withUnsafeRawPointerandMemoryLayout<Double>.strideto interpret the buffer as doubles and operate over the data with zero copies across the bridge.While I initially experimented with Apple’s Accelerate framework (vDSP) and standard arrays, I eventually dropped Accelerate, switched fully to
ArrayBuffer, and benchmarked in a Release build. That combination alone — Nitro’s zero‑copyArrayBuffer+ pointers + Release mode — was enough to make the native implementation around 11.16× faster than the JavaScript cosine similarity from the Vercel AI SDK in my tests.Through this project, I learned how to:
- Use Nitro Modules effectively and avoid performance pitfalls like passing large standard arrays across the JS ↔ native bridge
- Work with
ArrayBufferandFloat64Arrayon the JS side to achieve zero‑copy data sharing with Swift - Use Swift’s
UnsafeRawPointerandMemoryLayoutto treat raw buffers as typedDoublearrays safely - Benchmark correctly by comparing JS vs native in realistic conditions (Release builds on a real device)
- Structure a React Native library with an example app and documentation that focuses on practical performance tradeoffs
The result is a small but focused example of how to re‑implement a JS cosine similarity function in Swift using Nitro Modules and
ArrayBuffer, and make it significantly faster while keeping the API simple for React Native apps.CoffeeMasters: A SwiftUI app I built while taking Maximiliano Firtman’s Introduction to iOS App Development and Swift course on Frontend Masters. I went beyond the course by adding features like Likes, Filters, and Alerts to make it more interactive.
Through this project, I learned the fundamentals of Swift and SwiftUI — including working with state-driven UIs, optionals, reactive updates, integrating external libraries such as AlamoFire and integrating UIKit (usingUIViewRepresentable) to embed a WebView.
Built with SwiftUI, Xcode 15, and runs on iOS 17+.Foods: A pizza ordering app I used to learn react native, expo, and supabase.
DropShipNG: An e-commerce app I built for students at my local university to buy and sell items to and from fellow students. Never launched because at the time I was too young to register a business in Nigeria. I plan on launching it in the near future.
Suzy: Suzy is a simple image and text AI chat app, that generates flashcards for you based on the text and images you send to it. I built this to learn how to use Vercel's AI SDK I learnt how to use structured outputs with this project. (yet to upload code on github)
Aora: Another app I built when I started with React Native. It's a platform for sharing AI generated video. The course was taught by JSMastery on YouTube.
MotifMedia: A backend I built in Django for a company I and my friends started immediately after high school.
Currency Converter: A website I built to convert amounts in USD to different currencies while doing the Web Programming with Python and Javascript course by Harvard CS50. I also used my first api here lol, Shoutout to Brian Yu and Prof. David J Malan for this awesome course!