Spec-Driven Development with Holly Schilling

Spec-Driven Development with Holly Schilling

Jul 25, 2026

Scott Keck-Warren Holly Schilling

In this episode, Scott talks Holly Schilling about her work on the php tek 2026 mobile app and spec-driven development.

Links:

Holly's Links: Discord: TheCodeLorax Mastodon: https://tech.lgbt/@TheCodeLorax Blog: (coming soon) EventuallyWrong.com

Scott's Links:

PHP Architect Social Media:

Subscribe to our magazine: https://www.phparch.com/subscribe/

Partners

This podcast is made a little better thanks to our partners.

Displace

Infrastructure Management, Simplified Automate Kubernetes deployments across any cloud provider or bare metal with a single command. Deploy, manage, and scale your infrastructure with ease. https://displace.tech/

PHPScore

Put Your Technical Debt on Autopay with PHPScore https://phpscore.com/

CodeRabit

CodeRabbit - Cut code review time & bugs in half instantly with CodeRabbit. https://www.coderabbit.ai/

Music Provided by Epidemic Sound https://www.epidemicsound.com/

phpc #php #communityCornerPodcast #podcast #phptek

Transcript

Scott Keck-Warren Scott Keck-Warren 0:05
Hello developers and welcome to the PHP Architect Community Corner, where we have conversations with members of the web development community. I'm your host, Scott Cech Warren, and today we're having a conversation with Holly Schilling about her work on the PHP Tech 2026 mobile app and what it's like being a mobile developer in the current year. Holly Schilling has been writing PHP since 20— or since 2001, back when PHP 4 was the hot new hotness and she was in no hurry to move to PHP 5. She leads engineering teams building mobile apps and SDKs, and she's a firm believer in choosing the right tool for the right job, which more often than not is PHP. Most recently, she has built the official PHP Tech 2026 mobile app, roughly 40,000 lines across iOS, Android, and PHP Laravel in just 2 weeks using the spec-first development approach she presented at the conference. Over the past 14 years, she has also built a series of SQLite and SQLCipher wrappers spanning Objective-C, Swift, Kotlin, in C#, and her work includes an app that is now part of the electronic flight bag solution used across many domestic US airlines. She's currently co-hosting the PHP Architect Podcast on an interim basis alongside Sarah Goldman, pairing Sarah's deep dives into PHP internals with Holly's more applied ship-it perspective. A US Army veteran, she stays close to the PHP world less for the language than for the people, a community she describes as friendly, open-minded, and some of the cleverest she's met. Which I can conclude is the case. Thank you, Holly, for finding some time to talk to us today.
B
Speaker B 1:37
Thank you for having me.
Scott Keck-Warren Scott Keck-Warren 1:39
Yes, absolutely. So, and your bio kind of already had it in there. Like, I really wanted to talk to you about the PHP Tech 2026 mobile app and how that kind of came to be about. Sure.
B
Speaker B 1:51
So, I mean, the full story of it goes back quite a ways. I actually used to work a job that had a very significant commute every day. I, at the time, picked up a lot of podcasts. This is back about 2016. And so I picked up a lot of podcasts, one of them being the PHP Ugly podcast way back in its infancy. And I started following them, started hanging around there because PHP is a language I use. Again, it's not my main language anymore, but it is a language I reach for quite a bit. And I still go to as my kind of default backend language whenever time I'm building a mobile app or any sort of tooling that needs backend support. So it was something that was good to keep me fresh when I wasn't using the language on a regular basis. So I started listening to John and Eric on a regular basis there. And that kind of progressed and over the years as PHP Tech got taken over by Eric and is being hosted in Chicago, which is fairly close to me, I started coming down there to attend. This year, as it was, I was speaking with Eric and he had made the sad announcement that the developer was unable to get an app built in time. And I said, no, we had 3 weeks, we're getting it done. So, um, anybody who ships code knows that's not the right answer. I've done short-term projects like that before with a terrible deadline, and they often don't go well. But kind of in the new world we live in with AI tooling and all those kinds of things available I thought that was a very realistic project to get done, and we made it. I don't know how many of you know the, the timeline. We literally got it approved by Apple and into the App Store at about 5 AM on the Tuesday that the conference started. So, um, very, very tight deadline, but we made it, and I'm really proud of how that app turned out.
Scott Keck-Warren Scott Keck-Warren 3:46
Yeah, and I really liked it. I was— it was nice to be able to go through and like pick the talks that I wanted to see. Um, and I don't— none of the— like, I know that like— and then they put— did push notifications to like give us updates on things, which was also very helpful.
B
Speaker B 3:58
Yeah, I made the mistake of giving Eric that ability, but he actually didn't abuse it too badly at all, and it turned out really well for them being able to communicate with all the kind of unexpected changes and room changes that happened during the conference this year.
Scott Keck-Warren Scott Keck-Warren 4:13
Yeah, it was quite a, quite a, like, a huge change on the first day for, for sure. Um, would you guys— if anybody hasn't heard, go listen to the the PHP Architect Podcast where they talk about all that. And so like from— so you wrote it in Swift, Kotlin, and PHP Laravel. And so like what is— what was the basis for doing it with all of those different languages?
B
Speaker B 4:36
So my two primary languages are Swift and Kotlin. They are the ones that I use every— literally every single day. And I can jump into those between the code bases and have very little transition period between them because I use them every day and so fluently. And so that was my original hope, was that maybe I could do it with native PHP to start with, but I'm not as familiar with those libraries. And that with the condensed timeline, I knew that would be a little bit of an extra overhead that could have been problematic. Um, so as I've got about 15 years experience in doing mobile apps, it was just kind of this the first-class choice to use the native platform tooling. The other part of it then is using spec-first development, the code is immaterial. The designing things, the declaring what the behaviors are intended to be all the way through. Once I had that done for iOS, it was kind of a simple one-shot, now generate the Android version and then go through and kind of do the nitpicking versions on that. So the previous perception of doing two native apps is twice as much code is no— like, I mean, it's still twice as much code, but it's not twice as much work anymore. Most of it can be done in 10 minutes of generating code through an LLM.
Scott Keck-Warren Scott Keck-Warren 5:54
That's a term that many people might have not heard, that spec-first development. Can you, can you talk to us a little bit about what that is and how that works? Sure.
B
Speaker B 6:01
So it's kind of the basis of the talk I gave at PHP Tech. If you took any new developer, it doesn't matter how senior, experienced, and knowing the platform that they are, and you throw them into your codebase, it's going to take them a ramp-up period. And, you know, for, for most senior developers, that is weeks to months before they're even competent in any sizable code base. So the idea that you can take an LLM, even if it is perfect, even if it has no flaws of its own, which is not the case, um, LLMs are inherently bad. That's where the vibecoding kind of memes come from. But the idea of throwing that into your code base and telling it to fix things is is a kind of a, a crazy notion on its own. So what I've found works really well is to first declare what the behaviors should be. It gives the opportunity for the LLM to look at the spec, see what the intended behavior is, look at the code to see how the code matches it, modify the code then to compare to the spec, and it gives it that feedback loop. So it's kind of test-driven development for an LLM. So you've already written that the spec to say what it's supposed to do. Now the LLM generates the code and modifies the code to see, does this now match that declared behavior? And when you generate new context, when you have, you know, you close your window for the day, you open a new fresh context the next day, you didn't lose all that information of what you were working on. It's all there in the spec to say, well, we declared this to be one behavior. I think it's going to be able to continue working this way. And the other aspect of it is that the strength of an LLM is translating languages from one to another. That's actually how they kind of came to be was translating spoken word from English to French, Spanish, whatever I'll say. Code is just another language. So once you have this written in English and you have all the behaviors declared, translating that to code is LLM strength.
Scott Keck-Warren Scott Keck-Warren 8:06
Yeah. And the thing I really like about it is like sometimes our product team will come to us with like a very, let's say loosely defined problem, right? And they'll be like, here, fix this thing. And then that allows us to go, okay, here's a spec we're gonna generate. And then we hand it off to them and say, is this what you want us to do? And then we can like iterate, like then there's a human, human digestible piece of it as well. That's always been like a huge benefit for, for our team. Um, we even called it spec-driven. Spec-driven development isn't what we usually call it. We usually just call like making a product document, um, or a product review document or something like that. It's not my forte, I should say. Um, but it is, it is very, very helpful, like, just with humans and with LLMs, even if, like, you know, this LLM thing turns out to be a flash in the pan.
B
Speaker B 8:48
So a company I worked for did exactly that. They had a very rigid procedure where if somebody had an idea for something, they'd first draft a one-pager, which is kind of your pie-in-the-sky goals. Then they would draft a PRD, a product requirements document. Based on that, the engineering team would draft a technical requirements document. This kind of condenses that process down to one where if you have an idea, build the spec, the AI can even find, can even parse that spec and look for things that are conflicting. It can help you draft it. It's very good at writing language from your conversations. Mm-hmm. The idea is to keep that persistent log of what the intended functionality is and If you have, instead of having, I'm picking on Notion. I actually really like Notion. So it's not going to sound like that, but I really do like Notion. But if you have a Notion document, Notion is in a lot of cases where documents go to die. People draft documents, they throw them in there, say, look what I made, and no one ever looks at it again. And that's not very useful. Meanwhile, if you keep that spec, all the detailed documentation in the repository with your code, it can be checked out. It can be versioned. It can be reviewed through PR process, it gives you a lot of flexibility for that. So in the case of like the PHP Conference app, what I had done was to use a monorepo pattern with separate folders for iOS, Android, and Laravel. And then I had a separate spec folder that had all these spec documents in there that declared the behavior, declared the interfaces, declared how the JSON schemas were. And now every time that I needed to modify something, I went through and I just checked and like, okay, let's look at the spec. What does it say? During the conference, I had a couple people who would point out 2 or 3 different errors that were in the app. Eric found one, for example, the plenum sessions where they were like the opening and closing sessions said they were in all rooms. And as much as I'd love to blame Eric for my problems and say it was a data issue, Actually, I found that bug and it was written in the spec. And that was my own mistake that as I was drafting this, I had wanted for the floating room bubble, if you will, to appear to be in all rooms. Instead, I drafted it to say it should be in all rooms and the LLM mistook my intention with that. Every bug that was presented to me, everything that we found, it wasn't a code issue. It was a— I declared a bug in my spec.
Scott Keck-Warren Scott Keck-Warren 11:30
Yeah, that's it. And that's always like both fun and annoying, right? Is like, it was like, oh no, I'm at fault here, not the other people.
B
Speaker B 11:37
It is like we, as developers, we all look back and we say like, oh, who wrote this garbage code? And it's always you. Uh, most of the time the worst victim is always yourself or the person who left before you. That's always fun to blame that person.
Scott Keck-Warren Scott Keck-Warren 11:50
But, uh, yeah, I always love blaming the other people. Yeah, it was like, it was the other guy, the guy who was here before me. Yeah.
B
Speaker B 11:55
So little do you, and so do you know they had the same problem you face right now and they've, they just solved it in the best way they But, uh, I'm really, I, I'm always a guilty party there. I'm sorry. Continue.
Scott Keck-Warren Scott Keck-Warren 12:06
Yeah, no, no problem. So I think that like ultimately, um, it, it was really like nice to have that. And I, I, I'm sorry. So I, I also find that like the fact that you're, do you have like all 3 code bases in the same repository is really fascinating. 'Cause like we have, so we have, we have a Laravel app and we have a mobile app and I guess dumbly we like separated them into 2 different repositories. And so like whenever we develop like a feature. That needs to change the backend, we have to like touch both repositories and have all this like back and forth communication. And I'm just going like, oh no, we just could have done that in one thing now. So that's a genius idea. I wish I had known about that earlier.
B
Speaker B 12:42
I'm actually going to push back a little bit even on my own idea for a moment. This is going to sound odd, but I have not historically been a fan of monorepos. In fact, coworkers of mine will know that I protested against it when the idea of moving to a monorepo pattern came up. Generally, I am against it because making small incremental pull requests has been the ideal workflow for a very long time in development. If you put up a pull request of more than 300, 400, 500 lines, a lot of the times that meant that you're, you're not chunking your work properly or anything of that nature. It is only with the AI-driven development that I think those rules have gone out the window. All the rules that we've had over the years that made development effective have changed dramatically. We now have the— having that ability to have multiple repository— multiple code bases rather, in a single repository allows AI tools to build better context for themselves and to update both ends of like a wire communication, for example, a JSON schema or anything like that, update both sides of that at the same time in the same PR. And that is incredibly powerful.
Scott Keck-Warren Scott Keck-Warren 13:52
Hmm. Yeah. And it seems like it would be like, like you said that and I was like, oh yes, that is a— that is going to work out really well for like this use case, I think. Right. Not necessarily for like others, but, but for like where you have mobile apps along with like a backend.
B
Speaker B 14:06
You know, I've heard— I don't work at any— I've never have worked at any of the big FAANG companies, but I've heard rumors that Windows is a single code, a single repository, and the idea that that probably 100 gigabyte, probably way more than that now actually, but that massive codebase could be a single repository. I think it has so many strengths, but it also probably gives them a lot of problems at this point. So I think there's a balance to be struck and we'll probably talk about at the end. I have a blog going up that's not up yet, but the name is important to me. It's Eventually Wrong. That like everything I do has its limits. Everything I've found, every time I've set a hard rule, there's always a point where it's— I'm eventually wrong. If you find a monorepo pattern is not the right answer, well, now it is. Or you find that it is, well, it has its limits. There is no absolute truth. There's no hard lines to draw in development. And that's where I have the mentality for just trying to ship code, just get it out there, and we can always revise it. We can always make it better, but let's just get it out there.
Scott Keck-Warren Scott Keck-Warren 15:16
Yeah, and I have to like, I also agree with that. Like I've been, um, you know, I, I've been involved in programming for about the same amount of time as you have. Um, and so I, I started in PHP 4 as well. And it's, it's interesting to me where like we started out and we, we were originally doing things one way and then like the technology changed and we started using virtual machines and then we started using Docker containers and now like we're looking back at like other, you know, like it's just like there's always some change into how like best practices exist. Right. And it's always, it's always hard to know, well, I made a decision now that's going to affect me in 10 years, but it was the right decision at the time. It was the wrong decision 10 years from now, essentially.
B
Speaker B 15:59
You know, even before I was working in PHP, I learned in Quick Basic when I was in third grade. And then when I was in high school, I got excited about learning OpenGL. I wanted to be a game designer like every other coder in that, at that age. And so I started learning C and QBasic. C, neither of them really have objects. Moved to PHP 4, there's no objects. PHP 5 came out, why would I need objects? This is, this was ridiculous. Why would anybody ever need these tools? And here we are today and objects rule the world and we just live there. Yeah.
Scott Keck-Warren Scott Keck-Warren 16:35
Yeah, no, it's— and I same. I'm like, again, it's shocking. Like I started with QBasic. I did that gorilla game that the gorilla threw the bananas and you exploded things and you'd go, we'd mess with the gravity and stuff like that and see what happens. Um, so, so that, and that's, that's all really fascinating. And we'll be back after this word from our sponsor. Building PHP applications is your passion. Managing cloud infrastructure shouldn't be your headache. Displace is your partner in cloud infrastructure orchestration, giving solo developers and small teams the tools and automation to deploy enterprise-grade Kubernetes clusters without enterprise-grade complexity or cost. Their CLI tool streamlines everything from local development to fully managed cloud deployments on AWS, Azure, GCP, and more. Skip the steep learning curve of Docker, Kubernetes, and Terraform. Let our automation free you to focus on your core business without losing control over your infrastructure. Get started at displace.tech and discover how the right tools can eliminate the need for a full DevOps team. So can you tell us like a little bit about like, what is it like in doing mobile development in the modern 2026 world, right? Like we've, we've had this, this technology for over a decade and, and what is it like as, as a developer within native mobile app development?
B
Speaker B 17:51
So I started in mobile development in iOS 3.2 to, to put this into perspective. It was right as the iPad had been announced but not released. I got kind of challenged to building a mobile app for somebody, an iPad app for someone. Um, they literally said, we don't think you can do it, but we'll give you the opportunity anyways because we don't have anybody who's an experienced developer. And I jumped on that and I loved it. And that's kind of where I stuck for quite a while. Back then, mobile could do things that the web could not. That was what it was for, is because the Objective-C code or even the Java code on Android around the same time could compile down, it could be faster than what JavaScript, what the web was able to give a person. Even the JavaScript engines were not as performant as they are now. And that gave native a huge advantage, but it came at the cost of we had to manage your own memory, you had to manage threads and thread safety. There was a lot of sharp edges. The tools were bad. But that's what we did so we could do things that were incredible you couldn't do on the web. 2026, Chrome is amazing and it can do almost everything that a native app can do. And so the questions come in, why do mobile apps really even exist anymore? And the answer to that is kind of what, what I feel and what I push for to guide if a mobile app should even exist. A lot of people, and this is— a lot of people will take and say, well, I can take my Laravel website, put it into a PhoneGap, Cordova, any of those Ionic kind of wrappers, and I can ship my website as an application. There's no point in doing that if your users can already do all the functionality on the website. What makes a mobile app special is usually more about the persistence. About having that data pooling, the offline capabilities, then things like that, if your app is not one that benefits from that kind of thing, it generally doesn't need to exist. That's why a lot of the mobile apps I worked in over my career have been for banking, for finance, and things like that, where the security gains of having access to fingerprint sensors and biometric data in general, Those have been crucial and having that platform as a kind of a second factor authentication rather than having every new login requires the MFA and cookies getting deleted and all that kind of stuff. That persistent storage and persistent data of the user is crucial. So it's one of the areas I kind of push back whenever anybody's designing a new app today. What should this app do? What makes it special? And the PHP tech app's a good example of that. It wasn't just a calendar. It wasn't just showing like, here are the available ones. Every user, the moment you download it, you got to pick your own schedule for it. It gave you a consolidated list of it. It gave you the persistent communications channels with the backend. I don't— I didn't have analytics in there, but I didn't see anybody at the conference using the live activities on iOS or the widget functionality on Android. But those were other elements that I'd put in there. Um, the discoverability on them was not great, so I did— I was not hurt. But, um, those are the kinds of things that native apps bring to the table, and they are the main reason to have a native app today rather than just building a website and letting people access your tool in there.
Scott Keck-Warren Scott Keck-Warren 21:38
Yeah, I didn't— I didn't know that we had those. I would have had that live widget going, like, if I had— if I had, uh, if I had known that, because I always loved that as a— as like a what's next. Oh yeah, that's right. So as opposed to opening it up.
B
Speaker B 21:49
On the iOS side, um, it was a button on the, on the agenda screen. There was a button on the top right corner that nobody noticed what it even was there for. I, I realized that after the fact, that was my mistake of discoverability. But again, given the timeline, I think we did okay.
Scott Keck-Warren Scott Keck-Warren 22:06
Oh yeah, I think you did amazing. I like, I, I was very, um, I've used other conference apps and it was, it was very nice to use. Um, and it like, it was nice to do. It was very easy to just go like, what are these? Am I picking? And it like, highlighted, oh, you've picked two in the same time slot. And like, then it like kept— let me keep track of where I was going essentially. So it was really like a nice add-on to what we were— what we had there at the conference.
B
Speaker B 22:31
Yeah, I thought it went really well. And again, handful of small bugs, but they weren't code bugs, they were design bugs or they were oversights. And as we were building it, that I was really happy to see that. The other thing, actually, I'll mention this, and I mentioned it in my talk a little bit. One of the strengths and weaknesses of spec-first is that you can do a lot very quickly. The downside of it is when you deploy, if you find out that there's some change that needs to be made and you just make it at that backend and you make it at a code level, that becomes a liability. Now, every single time you try and make a change, the spec says one thing, the code says another. The AI bot is told, err to the side of the spec, give the deference to the spec. And so it makes that change or reverts whatever change you have made there. So there are a few times in there when Eric, as he's trying to deploy our backend or my backend under the PHP Architect infrastructure, he had to make a few changes and those became liabilities as we were doing rapid iterations.
Scott Keck-Warren Scott Keck-Warren 23:36
Yeah, we have, we have it set up so that like if the, if the code, if you have a code change, it has to affect the spec. Like we have to change the spec first before we change the code because of that exact problem.
B
Speaker B 23:48
So yeah, and I've been working on getting a really— I've been playing a little bit with CodeRabbit for this. That is one of my goals, to have a very good bot for analyzing that and having a rule of like the spec must be updated to reflect the code changes. I haven't quite worked it out yet, but that is on my roadmap, something I'm really trying to get perfected.
Scott Keck-Warren Scott Keck-Warren 24:14
I've been, I find that like the thing that I've really, I'm past the like, let me use my code or let me use AI to develop code. And now I'm to the, let me use AI to like review other people's code. Cause like, you know, like at work we have a review process and I just like, it would be nice if I could just have an AI, like we, we can't use CodeRabbit for reasons, but it would be just be nice if we could just like, I could just say, hey, go review this thing. Um, and, and, and, and just have them like have it do that. It's like, it's a really like fun, like exercise at the very least to try and get it to like get the right, give the right input or output essentially, or feedback to people as opposed to just being like a jerk to them, which it tends to be. I'm still working on that.
B
Speaker B 24:57
So I have come to like love and hate CodeRabbit and CursorBot, Cursor's bug bot. They are simultaneously, they've caught some great bugs, but they can be kind of brutal at times and it can hurt your feelings sometimes. Like I worked really hard and the bot doesn't care.
Scott Keck-Warren Scott Keck-Warren 25:14
I use CodeRabbit for a personal project. I'm amazed at like how much output it will create. Like I'll like make a minor change and it'll be like, here's a page of, of like how this impacts everything. And I'm just like, ah, so yeah.
B
Speaker B 25:27
Have you had any luck with the poems?
Scott Keck-Warren Scott Keck-Warren 25:31
Poems? No.
B
Speaker B 25:33
Okay.
Scott Keck-Warren Scott Keck-Warren 25:33
That's a new one to me.
B
Speaker B 25:35
Oh, it's not a Eric's installation of CodeRabbit. For PHP Architect. It was generate— it generated a poem on every time I did a pull request. Oh, it was a poem about the changes. You could argue it's kind of a waste, maybe boiling the oceans for nothing, but I rather enjoyed it. And there was one in particular that it, um, it was for the entire version of vendor mode for the app. I had done another probably 8,000 lines and I did it through a single PR. That's a bad practice, I'm aware. That was terrible. But It gave CodeRabbit enough material to actually write a reasonable poem about the contents and what it did. And it was just like a little 8-line thing, and it was just fascinating and made my day.
Scott Keck-Warren Scott Keck-Warren 26:22
Hmm. Although I don't, I don't get those for some reason. I wonder if that's a feature I have to turn on or something.
B
Speaker B 26:26
Yeah, it might be a feature to turn on or off. And usually if you do a 1 or 2 line code change, it like doesn't make sense, right? Because you can't write an 8-line poem about that. But if you do an 8,000-line change, that it actually has enough to write about.
Scott Keck-Warren Scott Keck-Warren 26:39
Oh, okay. So unfortunately, like, I have to draw this conversation to a close. Is, is there anything that you want to direct our listeners to before I let you go for today?
B
Speaker B 26:47
You know, I'm happy to always talk to anybody in the community, uh, or anybody who's interested in becoming part of the community. As I mentioned kind of in my intro, I love this community. They are great people, and I think more people should join, even if you're not coding every day in PHP. There are so many great people here, so many great minds, that I love to reach out and talk to them and bring them in to meet people. So I'm always there in Discord. You can find me, I'm TheCodeLorex. Um, I also have, um, my Mastodon that you could reach out to me there, um, TheCodeLorex@lgbt.tech. Uh, either one of those, I'm happy to reach out and always available to talk. So that's about it.
Scott Keck-Warren Scott Keck-Warren 27:27
Awesome.
B
Speaker B 27:28
Thank you.
Scott Keck-Warren Scott Keck-Warren 27:29
Thank you very much for finding some time to talk today.
B
Speaker B 27:31
Thank you for having me.
Scott Keck-Warren Scott Keck-Warren 27:33
Yeah, absolutely. I have to say another heartfelt thank you to Holly for all of her time, as well as for you for listening. If you're not a subscriber, Make sure you subscribe with whatever your preferred method is. This podcast is available both in an audio version on our website and a video version on our YouTube channel. And please like and subscribe so you get the latest as they're coming out. This is Scott Keck Warren for the PHP Architect Corner signing off and reminding you, keep listening, keep coding, and keep reading.