I took a client on in February for a mobile app. Another developer had built some infrastructure and I told them that I might try to save some of the infrastructure.
We made an agreement for certain features, including a style redesign.
Since that time, we had several meetings, the style design grew larger than I initially anticipated (I expected around the same complexity as the last design, instead it was more complicated). They've also been consistently adding new style requirements, like animations, new pages, new layouts, etc.
I also decided to integrate with a large part of the devops as it was enterprise level. I could have delivered a much smaller devops setup (I'm not a devops engineer), but I chose to try to preserve it as it would serve my clients long-term goals better. I don't feel I've communicated that well, as now the project is about two months late (due to the aforementioned stylistic parts, as well as this devops stuff).
My client is incensed. The app is late, and extremely so. But their employees have been asking for changes, and this devops stuff has just been a gigantic mountain of work for me. I finally finished it, but I had to learn Docker, Kubernetes, and an identity management system from scratch.
I realize that in the future I need to get an explicit contract with the exact features my client wants (we never discussed the exact server architecture or anything like that, and I'm not sure that the client understands enough to know whether or not this is valuable to him).
All I know is I am exhausted, I have worked extremely long hours over the past couple months and they're still angry. I haven't even billed since early April as I wanted to ship before billing.
I feel this is a combination of my and my client's fault (mostly mine), but how do I deal with them? Do I just say sorry and keep working? Try to explain what's happening and why things have taken so long? I'm working constantly on this and have been for months, and my client is extremely angry for non-delivery right now.