Zirve Asansör — Elevator Maintenance Platform
My father runs an elevator maintenance company in Trabzon.
The six projects

Backend — One REST Contract Over MySQL

Yönetim Paneli — The Boss's Desktop Panel

Yönetim PWA — The Boss's Panel on an iPad

Müşteri PWA — Apartment Manager's App

Teknisyen — Field App That Works Offline

Beşikdüzü Asansör — Marketing Site
The problem
The company had no software at all. Dues were kept in a notebook, payments were cash handed to my father, and which buildings still owed money for which months lived in his head. When a manager argued about a balance there was nothing to point at.
Apartment managers are mostly older people, not comfortable with technology, and they change every year or two. Anything built for them had to work for someone holding a phone in a stairwell. The technicians spend their days in machine rooms and basements without signal, which ruled out an app that needs a connection to save a visit.
Architecture
One Node and Express backend over MySQL owns everything. It is the only thing that touches the database and the only thing allowed to change the API contract. Each client is its own repository, written against a copy of that contract, and not allowed to edit it.
The desktop panel is JavaFX. I chose it partly because I know Java and partly because a desktop client can't cheat: it forces the API to be complete from the first day. The iPad panel is a web copy of the desktop one, screen for screen. The customer app is a PWA installed from a link or a QR code, because a native iOS app can't be distributed outside the App Store and these users were never going to search a store. The technician app is React Native, since it needs offline storage and, eventually, push.
Under all of it, every record belongs to a building and never to a person; the manager changes, the debt stays. A balance is never stored. It is the sum of valid dues minus the sum of valid payments, recomputed every time it is asked for. Nothing financial is deleted; a wrong payment is cancelled with a reason and stays visible. The one exception I allowed is a repair charge line, which can be removed outright.
My role
A solo project, and the decisions were mine: the architecture, the data model, the API contract and how each screen should behave. I drove the implementation with AI coding agents, documentation first. There is one architecture document and one contract. Every client session was pointed at those files and told it could not change them; when the contract had to change, the backend changed it and the copies were refreshed.
The parts I had not built before, the offline sync queue, push, Docker with Caddy, the JWT details, I listed up front as zones where I was learning rather than directing, and I read those harder than the rest. The rule I kept for myself: a file I couldn't explain didn't get committed.
Scale
Six repositories and 168 commits between June 12 and September 16, 2026. The backend is 28 SQL migrations, 15 tables and 58 endpoints, with fourteen test suites; the ones that touch a database refuse to run against the real one. The contract went through thirteen revisions on the way, each recorded with its date and its reason. In the business it covers about 300 buildings in two cities, four technicians, and one person collecting the money.
What I took from it
Three things I built were wrong and had to be replaced, and they taught me more than the parts that worked.
The first version of payments put maintenance dues and repair charges in one pool and paid off whichever was oldest. It was tested, it was correct, and in practice it confused my father: money handed over for a repair could land on an old maintenance month. It lasted a day. Then payments got a type, and the two debts got separate books.
Customer login started as a building code plus a required password, sent over WhatsApp. Around 300 managers, most of them older and not comfortable with technology, were never going to be onboarded that way. Login became the manager's phone number. The password became something you add if you want it.
The technician home screen was first built around days: a strip of dates, tap one, see that day's work. The technicians don't work by day. They work by district. That screen lasted two days.