October 13, 2026Online track4 min read

Please… Enough with the Sloppy, One-Shot SaaS Replacements

A working internal app can still be unpleasant to use. Mahmoud Abdelwahab walks through the product details, reusable patterns, and verification loop behind Railway’s agent-built marketing tools.

Mahmoud AbdelwahabRailway

From the conference livestream · 3:48:40–4:01:59 on YouTube. The player starts and stops at this session’s boundaries.

3:48:40 ↗

Working software is the starting point

Getting an agent to generate a working SaaS replacement is one thing. Using it all day exposes what the first attempt missed: lost edits, slow feedback, inconsistent pages, and awkward ways to move through records.

Mahmoud Abdelwahab encountered that gap while replacing several of Railway's internal marketing tools with one application. It handles website content, the changelog, the blog, email, social publishing, and media. A small CRM tracks relationships with external creators; task tracking, launch planning, and a calendar coordinate releases. Comments and collaborative editing support work shared across the team. Building the feature list was only part of making the application feel coherent.

The Mini CRM below puts creator relationships into a familiar board, alongside the same application’s content and planning tools.

Railway’s internal Mini CRM groups creator engagements by status, with shared content and planning navigation alongside it.

The application at 3:49:28. Keeping those jobs in one interface gives the team a starting point for consistent navigation and interaction. The rest of the work is making those interactions good.

His first principle is to give the coding agent a structured codebase with useful abstractions. The language or framework matters less than having patterns worth repeating. When the agent adds a feature, an existing approach to layout, fetching data, and updating records lets it extend the product without inventing another way to do the same thing. He mentions TanStack libraries for web work and Payload for content-heavy applications, preferring an established CMS to rebuilding those capabilities himself. 3:50:53

From a bench in Edinburgh, Abdelwahab works through the details he learned to ask for after using his own tools.

3:52:43 ↗

The details you miss until you build them

Commercial tools hide years of product decisions inside apparently simple actions. Sending an email or publishing an item can work through a conventional form submission. Frequent use exposes the friction that implementation leaves behind.

  • Keep the writing moving. In a document editor, typing should continue while changes save in the background. A warning before closing a tab with unsaved changes supplies another layer of protection. Real-time collaboration can go further, but the basic requirement is that ordinary work should not disappear because the user forgot to press Save.

  • Show the result promptly. Optimistic updates address a different delay. The interface can show the intended result immediately, then synchronize with the server. If the operation fails, it rolls the change back and explains the failure. Abdelwahab does not recommend doing this for every operation: some actions should wait for confirmation. The useful move is to ask the agent which actions in this particular product can safely feel immediate.

  • Let users recover from deletion. A confirmation dialog asks users to decide before seeing the result. A short undo window can remove the item immediately while postponing the destructive operation. If the user changes their mind, the item returns. Archiving serves a separate purpose: users should be able to hide records without being forced to destroy them.

  • Make views easy to revisit and share. Filters and sort settings stored in the URL let one teammate send another the same view. Infinite scrolling avoids repeated clicks on Next or Load more when browsing long lists. Neither is a substitute for correct data handling, but both change how much effort a frequently used application demands. 3:53:38

The surprising part is how little of this requires a new model capability. In Abdelwahab's experience, the agent can implement these behaviors. It often needs the person directing it to know that they should exist.

3:58:14 ↗

Make good choices reusable, then use the result

Once one page behaves well, ask the agent to use it as the reference for similar pages. Two sections that both list, create, update, and delete records should share an interaction pattern. This gives the agent a concrete example of good work instead of making it reconstruct a vague preference. He notes that models still sometimes ignore the instruction; an explicit reference improves consistency without guaranteeing it.

Preferences that recur across projects can become agent skills. Abdelwahab used skills for layout, typography, and error messages; another set covered animation and design engineering. Railway's own skills helped the agent deploy the application and its supporting databases, buckets, and real-time server.

The final step is verification through actual use. An agent announcing that the build and tests pass may still have produced a broken experience. Abdelwahab asks it to run the infrastructure, use the feature end to end, discover the failure, and keep fixing it. Computer use made that loop substantially more useful in his experience. 4:00:26

A passing build cannot tell you whether editing a draft feels safe or whether two colleagues can share the same filtered view. Use the application, find the awkward part, and give the agent a concrete behavior to repair. Taking responsibility for those details is how an internal replacement becomes a tool colleagues want to reach for.

Further reading

Full transcript 178 timestamped passages

Machine transcription with reviewed terminology and names. Some recognition errors may remain. Timestamps refer to the livestream; subtitle downloads are timed to the session clips.

3:48:40People have been saying that SaaS is dead for a while now.

3:48:43It's not even a hot take at this point.

3:48:45Why pay someone to build and maintain the tools you use when you could just do it yourself?

3:48:50Just ask your agent to do it.

3:48:52And for me, there's one missing piece that rarely gets mentioned.

3:48:56And it's the fact that there's a gap, a big gap between working software that got one-shotted

3:49:01and software I would actually use.

3:49:04Software that sparks joy, that is polished, that feels good.

3:49:07And I actually went on a journey to replace a bunch of SaaS providers we were using internally

3:49:11at Railway for marketing purposes.

3:49:13And I just built an all-in-one tool that we use.

3:49:16The tool allows us to manage content

3:49:17for the Railway website, change log, blog.

3:49:20We can use it to send emails,

3:49:22post on all of our social platforms at the same time,

3:49:25manage the website's media.

3:49:26There's even a mini CRM so that when we're working

3:49:29with external creators, we can keep track of that.

3:49:32There is task tracking, launch planning,

3:49:34because you wanna coordinate multiple things

3:49:36and when they'll go out, there's a calendar.

3:49:38and at the same time there's like comments real-time editing and it's all built using

3:49:45agents i would say i felt the breakthrough when gpt6 came out and all of this is running on railway

3:49:52everything just auto deploys and let me essentially now walk you through the principles i use

3:49:58to actually make sure that when i want to add a feature it's you know actually polished and

3:50:04matches the rest of the app and at the same time the principles that you can pull from and apply

3:50:11when building tools of your own so instead of doing my talk from my boring office i decided to

3:50:16switch things up and do it outside it is absolutely beautiful right now i'm in edinburgh scotland

3:50:21and it's just unreal like i'm on a bench outside and this is my view definitely a 10 out of 10

3:50:30bench. Now, this type of talk for me feels a little bit different than what I'm used to, because

3:50:36I essentially will walk you through the journey of me building our own internal tools and the

3:50:42opinions I've developed. But I also understand that the landscape changes very, very quickly.

3:50:48So like anything I say might change completely in like the span of months. Who knows? So I don't

3:50:57know consider this my disclaimer like but the time of recording is fall 2026 it's october and

3:51:04yeah so anyway with that out of the way uh let's talk about the first point which is text acts don't

3:51:12matter now a lot of people say that it doesn't matter what programming language you use what

3:51:17framework you use you can just ask your agent to go do anything and those are able to do it

3:51:21And while I agree to some extent, what I found is when you're building a tool that you will actually use, when you give the agent a proper code base with solid abstractions, what ends up happening is whenever you're working, let's say, on a new feature, you end up with a much more consistent result that is similar to what you've already built before.

3:51:44And the reason is, like, it's very simple.

3:51:47The agent doesn't need to reinvent the same, like, wheel every time it tries to add a new feature,

3:51:53or it doesn't need to introduce new patterns.

3:51:55It will just essentially follow existing patterns.

3:51:59And when it comes to, like, what you choose, I feel like it kind of doesn't really matter

3:52:03as long as you have a code base that is properly structured.

3:52:08But my go-to choice today is, one, TanStack libraries for anything when building on the web.

3:52:15And if you're building anything content-related, I would say definitely go with payload.

3:52:19Solid experience, great abstraction.

3:52:21I went down a big rabbit hole of comparing CMSs at some point because I don't believe that I should build it from scratch, even though I can.

3:52:30But again, who knows?

3:52:32Maybe the future will change.

3:52:33but yeah and that's kind of like the main first item that i kind of ran into

3:52:44when you use like a lot of sas products out there that you actually love they use every day

3:52:49when you're a user there's like a lot of things you don't notice but when you actually try to like

3:52:54replicate an experience you quickly find out how much care and thought goes into different flows

3:53:01So something as simple as, oh, I want to be able to send an email or to publish something.

3:53:09You can easily do it by having a good old server-side rendered app with forms that you submit.

3:53:18But if you try to build something that is going to be used every day that you will reach for

3:53:23a lot, you're like, oh, it shouldn't feel that way.

3:53:27And there are kind of like a bunch of patterns that I found that agents don't typically do unless you explicitly ask them to.

3:53:35And this is my list. So we'll go through them one by one.

3:53:39And the first one is like autosave. I found that if, like, let's say I'm building some form of document editor, autosave is kind of like a table states feature.

3:53:49So rather than manually clicking save to save things, you just ask it to automatically save progress in the background and to make sure that it's like a non-blocking action.

3:54:02So that you can, let's say, as you're typing, you're able to type and then it just automatically saves.

3:54:08And one other kind of like step further that you could do is to also prevent the browser tab from closing if there are unsafe changes.

3:54:20So it's kind of like these two layers that kind of guarantee that whatever it is that you're working on is just not going to be lost.

3:54:27Now, you can also go a step further and to add like real time collaboration so that you can have like concurrent edits.

3:54:35And again, my agent didn't struggle at all with adding the feature.

3:54:39It was like, I don't know, asking about it, reviewing how it would work.

3:54:45And then once that's done, just 700 million tokens later, I had real time.

3:54:50So I would say in general, this is the first thing that I find agents just don't do well from a product experience perspective.

3:54:58Another pattern I found that agents completely forget to implement is optimistic updates.

3:55:02So rather than showing your users a bunch of loading spinner whenever they're taking any action,

3:55:07you essentially show them the success state optimistically.

3:55:11And in the background, you're going to sync whatever change they made.

3:55:15Now, if the sync or the operation fails for whatever reason,

3:55:19you just roll it back and then tell them, like, oh, the operation didn't work.

3:55:23Now, of course, you shouldn't blindly have optimistic updates for everything.

3:55:27There are some scenarios where you want to show the user a loading spinner

3:55:31and they're going to wait to check that everything worked properly.

3:55:35But in general, having optimistic updates

3:55:37makes the overall experience feel significantly faster,

3:55:41much snappier, and it will just feel much more instant.

3:55:45So pretty sure you can just ask your agent like,

3:55:49hey, I would like to implement optimistic updates where it makes sense.

3:55:52Let's come up with a plan and it will tell you all the areas

3:55:54where it makes sense to do.

3:55:55Again, it's like it's not difficult for the agent to build it.

3:55:58you just need to ask and know exactly what to ask for. Now an extension of optimistic updates in my

3:56:04opinion is giving users the ability to undo certain actions. Now for example if you ask your agent to

3:56:11implement the ability to delete records what it will typically do is it will give you a delete

3:56:16button you click it might show a confirmation dialog you hit confirm and then it will actually

3:56:21do the deletion. But a much nicer experience is actually allowing the user to undo that action

3:56:28so they could delete you immediately remove the item they want to delete from the ui but you tell

3:56:34them like hey you have like a couple of seconds where you could change your mind and if they don't

3:56:40do anything that means you actually want to delete a thing then you actually implement the operation

3:56:45otherwise if they hit undo you just bring back the change so it's kind of like you do the operation

3:56:52in the background as well it's just kind of a delayed action which kind of ties into the next

3:56:57point, which is archiving, you should tell your agent you want the ability to archive records

3:57:03and be able to unarchive them. Because sometimes you want to hide something from the UI completely,

3:57:09or let's say from search results, and archiving will be the way to do it. And you shouldn't

3:57:14force your user to be like, well, if you don't want to see this, you have to delete it.

3:57:18Any much better experience is just the ability to archive records. So I think it is a pattern

3:57:24that should definitely exist.

3:57:26Another big one for me is URL state.

3:57:27You should ask your agent to persist in the URL

3:57:30whenever it makes sense, of course.

3:57:31And it's so useful because whenever you have,

3:57:33let's say, a list of records

3:57:34and you want the ability to filter or sort them

3:57:39and you just have a bunch of conditions,

3:57:42maintaining these things in the URL

3:57:45makes it trivial for you to give them to someone else.

3:57:47And then, let's say, another team member

3:57:49is just going to be able to see

3:57:51exactly what you want them to see.

3:57:52Now another small detail that agents don't implement out of the box is infinite scroll.

3:57:56I don't want to be clicking on lobe more over and over and over or like a next page button.

3:58:02As I scroll, I should just get the data.

3:58:05I shouldn't need to click next page.

3:58:07And then in the end, I'll just see that, oh, I've reached the end.

3:58:09It's a very minor thing.

3:58:11But also when you use something every day, I think it makes a huge difference.

3:58:15Now another pattern I found that made the output significantly better is telling the

3:58:20agent explicitly to use existing pages as references when it comes to the ui the data

3:58:26fetching and how it works and how the thing is overall structured and that made it possible for

3:58:32me to essentially define what good looks like once and then just reuse it for more features now

3:58:39to be completely honest sometimes even when you tell the agent like hey use page x as a reference

3:58:46sometimes it just doesn't follow it i don't know if models like get dumber sometimes but sometimes

3:58:52it does happen but overall i would say that my success rate is higher whenever i tell the agent

3:58:57to like well use an existing page as a reference because you also just end up with a more consistent

3:59:03experience so like as you're using your app you're like oh this just matches the other part of the

3:59:08app if they both share like the same concept so like if two parts of the app are essentially

3:59:14lists of records that you can create, update, and delete and list. Well, both of these parts

3:59:21should be pretty much identical. This list kind of brings me to my next point, which is whenever

3:59:26you have opinions about something, they should be packaged as agent skills. And then this way,

3:59:30your agent, whenever it's building something, it will actually follow those skills pretty closely.

3:59:36And as I was building all of our internal tooling, I found myself reaching for three agent skills.

3:59:41two of them are related to design engineering so one made it easier to have better ui better

3:59:47typography better layouts as well as like better error messages in general and the second one was

3:59:53a set of design engineering skills that made it easier to just have better animations and other

3:59:58things like that and then last but not least is the railway agent skills of course so like

4:00:02everything that i built for us internally at railway runs on railway of course like everything

4:00:09So like buckets, databases, the app itself, the real-time server, everything.

4:00:14And for the agent to effectively work with Railway and be able to deploy everything,

4:00:19you just give it the Railway agent skills and it was just able to do it.

4:00:23And yeah, so like once you have all of your agent skills and everything,

4:00:27in my opinion, the final step, and I think the most important step, is verification.

4:00:34So the agents typically, whenever you ask it to build something,

4:00:37it's going to be like, okay, I implemented the feature.

4:00:39build pass, test pass, all good, right?

4:00:42But what I found is when you actually try out what happens,

4:00:46you sometimes end up with just like a very broken experience.

4:00:51So once you have like a verification loop in place,

4:00:54it's like a nine day difference

4:00:55because the agent, you can literally see it,

4:00:58be like, okay, I built this thing.

4:01:00I tried it.

4:01:01It failed.

4:01:01I'm going to fix it.

4:01:03And it just keeps going.

4:01:04And then in the end, it's like, okay, I fully tested it.

4:01:06And I felt this breakthrough with computer use once it got really, really good.

4:01:11And now every time I want to add a new feature, I literally just in the end say, well, you should verify that the feature works end-to-end and use it by actually running infrastructure and to test things end-to-end.

4:01:26And the agents are very capable of doing this.

4:01:28You just have to tell them.

4:01:30and once you have all those pieces,

4:01:32I would say you will end up with solid internal tools

4:01:36that you can build quickly,

4:01:38that work properly and work in a consistent way.

4:01:40And that's it.

4:01:41This was my list of principles that I use

4:01:43whenever I'm building any internal tools.

4:01:44Hope you found them useful.

4:01:45But more importantly,

4:01:47that you're inspired to build your own internal tools

4:01:50that feel good, that are polished and spark joy.

4:01:54And I hope that you too can become your company's SaaS layer.

4:01:57And with that, thank you so much for watching, and I'll see you in the next one.