I notice what is easy to miss — in the interface, code and app behaviour
Attention, to me, is not only about pixel polish. I follow the whole scenario and check a risk even when the problematic code sits next to my task rather than inside it.
Mobile developer · React Native · Fullstack
I build mobile applications for iOS and Android — commercial products and my own, from product features through post-release support.
what matters to me and how it shows up in my work
Attention, to me, is not only about pixel polish. I follow the whole scenario and check a risk even when the problematic code sits next to my task rather than inside it.
When the same friction appears in several tasks, I look for a common mechanism and leave it in a form the team can reuse.
I work with existing code long enough to see its real connections. Small separations go in as small commits; changes that require holding the whole system in mind get a separately agreed window.
Where the client, backend, stores and external services meet, I make each state and transition explicit — including waits, errors, restarts and partial data.
A team, to me, is mutual support and real relationships, not only a shared repository.
Start with the highlights. Open any project to see every contribution and result.
React Native developer · Android, iOS
I joined before the public release. Set up subscription products in Google Play and the App Store, unified them behind RevenueCat and built the full purchase cycle. The stock RevenueCatUI screen gave way to my own: plan selection with a per-day price and the discount figure, purchase restore, promo-code entry, and a wait on the backend confirming Premium was actually granted. Promo codes come from three sources: AppsFlyer attribution, deep links and manual entry; an unfinished flow continues after an app restart, and when a code arrives from several sources at once the conflict is resolved. On top of that, server-driven promo offers and flash-sale banners with a countdown.
The heart of the product is the exam-test screen. Test state was distributed across a dozen nested components, each reading and writing global state, and any edit could easily break something next to it. I gathered it into a module with a single session state and one-way data flow, with my own card engine on Reanimated and Gesture Handler running inside it. I started by profiling and built diagnostics into the engine, then fixed what its readings pointed at: redundant React renders, animations depending on the JS thread, loading more cards at once than were needed. Freezes, dropped swipes and blank cards on low-end devices went away.
Separately I worked on the engineering base of the project. I moved the app onto FSD and wrote my own ESLint rules — they hold layer boundaries and code style and keep Storybook out of production, so a violation never reaches review. I documented the architecture, the harder subsystems and the release flow, and put together a separate set of instructions for AI agents: project structure, established patterns, what to reuse and where. Since then agents stop rewriting what the project already has, break layer boundaries less often and spend less context working out how the code is arranged — there is noticeably less to correct after them. Storybook opens from a deep link, so both QA and an agent can run a specific story; that took patching the Storybook library itself and a separate build that works without Metro. I moved React Native from 0.76 to 0.86 and onto the New Architecture, working through dependency conflicts and regressions on both platforms.
I took part in hiring React Native developers. For the interviews, I prepared questions that test understanding of React Native specifics and live coding in a real app with an emulator — the candidate had to find and fix a problem rather than reproduce memorised definitions. I ran the interviews and took part in the final decision. The developer who joined, I onboarded onto the project and reviewed their first tasks.
Screens
React Native developer · Android, iOS
An internal fintech startup: loyalty cards that let employees of large companies pay for fuel, restaurants and flights, with the accounting simplified for the employee, their company and the partners.
I was the only developer on this app across both platforms — from screens to builds, signing and the Expo SDK upgrade with the move to the New Architecture. The product went through two pilots with real payments: filling up by QR code from the app, charged to the loyalty-card account. Development has since stopped and the app stayed in the stores.
The partner map came from the backend as a single list, with no clustering. The backend team is busy, and the map is needed now. So ten-plus thousand markers have to load and run smoothly on the client, on top of Yandex Map, which has a thin set of ready-made solutions for React Native. I implemented tiled loading, clustering, viewport filtering and caching — the lag on panning and zooming went away.
Paying inside partner mini-apps went through two webviews. The app passed the initial data into the first one, waited while the user went through several steps in it, and — without closing it — opened the second, the payment one, passed the collected data in, took the result and handed it back to the first. I implemented the whole exchange cycle with error handling at every transition. I updated the contracts in the internal mini-app library and published the new versions to npm.
The shape of the API data could change unpredictably, and the app was not supposed to break. I designed a validation layer on the app side: a validator factory where the response schema is described declaratively and every field carries a criticality level — critical, replaceable or optional. A failure on a critical field stops the scenario, a replaceable one falls back to a default, an optional one is skipped — an incomplete response does not take the screen down, and the interface shows what it managed to get. Every mismatch goes to the logging system with the field and the context, so the team learns about a broken contract before the users do.
Built several forms with inputs, validation on the fly and on the server, and dynamically loaded suggestions. Reworked signing in to the app around a state machine, and made it comfortable to debug. Added sign-in through our service for third-party apps over OAuth: the third-party app opens «Счёт-бухгалтеру» through an intent, the user confirms with one button, and the session is returned to the calling app.
Set up builds in the Expo cloud and locally, and optimised the bundle size. Published the app to the stores, including RuStore.
React Native developer, .NET backend · Android, iOS, backend
Two cross-platform Löwenstein Medical apps, each paired with a therapy device over Bluetooth: real-time data exchange, therapy statistics, firmware updates, reports for the doctor. Medical software, with strict release rules. The cost of a mistake here is higher than usual: the data goes to a particular person's own physician.
I worked on both sides of the API: the React Native client and the .NET server. I took features end to end. Device-ownership confirmation went from server migrations and logic through to the screens: until the user confirms the device is theirs, it is cut off from syncing.
The interface broke systematically on devices with other screen and font sizes. At first I filed and fixed individual bugs myself, then ran a full audit of the app together with the designer. To see the result immediately I started three emulators with different settings and attached them to Metro at once, walking every screen on all configurations. I fixed more than 50 UI problems, pulled out reusable components and added text descriptions to image buttons for the OS screen readers — the app is used by people with low vision too. Out of all this I put together a 61-slide presentation and delivered it to developers from several projects, and wrote the rest up in the project Wiki.
I worked through production issues: tickets from Sentry and OpenSearch, requests from support, logs from real user devices. I dug down to the cause and turned it into a task — over a hundred bug reports, and I closed most of them myself.
I turned the test-data helpers for the automated tests into a factory of test scenarios: the state a test needs is assembled declaratively, so a new test starts from a description of the situation.
On the backend I split an overgrown service into three. Together with a colleague I reworked two closely related classes: the shared part moved into an abstract class, leaving two explicit implementations. I brought the initiative to a retro.
Fullstack, solo · React Native, Expo, NestJS
My own product, both halves written by me: a day planner, hierarchical tasks and goals, notes with categories, a habit tracker with statistics, a time tracker that exports to an external service, and an AI assistant with streamed answers. The app builds and runs on a device, and the server runs under PM2 on my home machine. Active development.
The day planner is a timeline where a block's duration changes by dragging: gestures on Gesture Handler, animations on Reanimated with shared values, snapping to a five-minute grid, and an enlarged touch area so a finger can catch the edge of a block. The heat map for habit statistics I wrote myself, without charting libraries.
Notes work offline on the outbox pattern: operations go into a persistent queue, a separate sync engine works through it and tells temporary failures apart from conflicts, and once an entity is created it maps the temporary client id onto the server one.
The AI assistant streams its answers over SSE. React Native's built-in fetch does not hand back a stream, so I took a separate SSE client. Finishing an answer was a problem of its own: because of tool calls, one user message produces several completion signals, so finalisation goes through a deferred timer.
The server is a NestJS REST API: thin controllers, logic in services, validation of every incoming payload with undeclared fields stripped, OpenAPI generated from the DTO descriptions. Two authentication mechanisms for two kinds of client: JWT for the app, and an API key for the AI agent, tied to the user through its own entity. The schema lives in Prisma and moves through migrations — task hierarchy through a self-reference, deliberate on-delete behaviour, composite indexes for cursor pagination.
In the time tracker, starting or editing a record resolves interval overlaps: absorbing an existing record, trimming it from the left, trimming it from the right, splitting it in two. Shadow records let a finished record be overridden for reporting without touching the original data. Time is stored in UTC everywhere but grouped by the user's local day from a client-supplied offset, and the pattern is applied consistently on both layers.
Integration tests on Jest and supertest run against a separate test database and cover auth, notes, categories, projects, the tracker, sync with the external service and the agent API.
Fullstack, solo · NestJS, Telegram bot
A server application for the production cycle: clients, orders, product configurations, components, work orders and financial operations. The interface is a Telegram bot with roles: the manager and the master see different scenarios. I built everything from the data model to the user dialogues.
At the core of the bot is a generic multi-step scenario handler that processes data for every entity. A step is defined by its field type — string, number, date, flag, list selection or a custom type — and the engine builds the dialogue, validates input and assembles the entity. It is written with generics bound to the base entity type, so one engine serves clients, orders, configurations, components, stock-in, stock-out, work orders and finance.
For component accounting, the data model uses two independent stock-in and stock-out journals instead of a mutable balance, preserving movement history rather than only the current value. Union types are stored as keys and mapped to labels in one place through ORM transformers; receiving components automatically creates a financial operation.
School years
I won city programming olympiads and competed at regional level. I never pursued competitive programming seriously, but I understand algorithms and have liked problems whose solution is not obvious ever since.
2009–2013 · from ninth grade
I ran a website about games and films connected to the regional forum. I refreshed its layout, added ratings and a member recognition board, wrote news publishing guidelines and coordinated a team of 5–8 moderators and news writers.
University years
Our team won the regional round of Microsoft Imagine Cup and continued developing the project for several years. The system showed a person a set of images and recorded their gaze trajectory; the idea was to apply the technology in amnesia therapy.
We built the first prototype around a regular webcam, implementing face recognition and pupil coordinate detection ourselves, then moved to a professional eye tracker. I built a WPF desktop application for running the tests and a separate results viewer that loaded coordinate logs and replayed gaze movement over the images like a video.
Project for the Ministry of Education
I built a small tool for education staff: a map for analysing and correcting how exam participants were assigned between schools — which school they came from and where they would sit the exam.
I run AI models locally and experiment with using them outside the cloud.
I design parts and print them on a 3D printer.
I set up Proxmox and Linux servers for different tasks.
I made a mobile app to help her learn to count large numbers.
If any of this is worth a conversation, the fastest way is Telegram.