WEBVTT

NOTE Sentence-level transcript of https://www.youtube.com/watch?v=oixzVKMAXG0

NOTE One cue per sentence. Cue ids are the line anchors on /transcripts/oixzVKMAXG0.html. A cue ends where the next begins, or 2 s after its last word.

s1
00:00:00.400 --> 00:00:03.120
People have been saying that SAS is dead for a while now.

s2
00:00:03.120 --> 00:00:05.279
It's not even a hot take at this point.

s3
00:00:05.279 --> 00:00:10.160
Why pay someone to build and maintain the tools you use when you could just do it yourself?

s4
00:00:10.160 --> 00:00:11.920
Just ask your agent to do it.

s5
00:00:11.920 --> 00:00:16.240
And for me, there's one missing piece that rarely gets mentioned.

s6
00:00:16.240 --> 00:00:23.680
And it's the fact that there's a gap, a big gap between working software that got oneshotted and software I would actually use.

s7
00:00:23.680 --> 00:00:26.800
Software that sparks joy, that is polished, that feels good.

s8
00:00:26.800 --> 00:00:33.440
and actually went on a journey to replace a bunch of SAS providers we're using internally at Railway for marketing purposes.

s9
00:00:33.440 --> 00:00:35.760
And I just built an all-in-one tool that we use.

s10
00:00:35.760 --> 00:00:40.000
The tool allows us to manage content for the Railway website, change log, blog.

s11
00:00:40.000 --> 00:00:46.239
We can use it to send emails, post on all of our social platforms at the same time, manage the website's media.

s12
00:00:46.239 --> 00:00:51.520
There's even a mini CRM so that when we're working with like external creators, we can keep track of that.

s13
00:00:51.520 --> 00:00:57.199
There is task tracking, launch planning because you know you want to coordinate multiple things and when they'll go out.

s14
00:00:57.199 --> 00:01:05.280
There's a calendar and at the same time there's like comments, realtime editing and it's all built using agents.

s15
00:01:05.280 --> 00:01:12.479
I would say I felt the breakthrough when GPT6 came out and all of this is running on railway.

s16
00:01:12.479 --> 00:01:14.240
Everything just auto deploys.

s17
00:01:14.240 --> 00:01:28.159
And let me essentially now walk you through the principles I use to actually make sure that when I want to add a feature, it's, you know, actually polished and matches the rest of the app and at the same time

s18
00:01:28.159 --> 00:01:32.960
the principles that you can pull from and apply when building tools of your own.

s19
00:01:32.960 --> 00:01:38.240
So instead of doing my talk from my boring office, I decided to switch things up and do it outside.

s20
00:01:38.240 --> 00:01:39.520
It is absolutely beautiful.

s21
00:01:39.520 --> 00:01:43.600
Right now I'm in Edinburgh, Scotland, and it's just unreal.

s22
00:01:43.600 --> 00:01:48.240
Like I'm on a bench outside and this is my view.

s23
00:01:48.240 --> 00:01:51.280
Definitely a 10 out of 10 bench.

s24
00:01:51.280 --> 00:02:03.680
Now this type of talk for me feels a little bit different than what I'm used to because I essentially will walk you through the journey of me building our own internal tools and the opinions I've developed.

s25
00:02:03.680 --> 00:02:08.319
But I also understand that the landscape changes very very quickly.

s26
00:02:08.319 --> 00:02:15.120
So like anything I say might change completely in like the span of months.

s27
00:02:15.120 --> 00:02:15.920
Who knows?

s28
00:02:15.920 --> 00:02:16.560
So I don't know.

s29
00:02:16.560 --> 00:02:17.760
Consider this my disclaimer.

s30
00:02:17.760 --> 00:02:22.080
Like but the time of recording is fall 2026.

s31
00:02:22.080 --> 00:02:23.599
It's October.

s32
00:02:23.599 --> 00:02:25.040
And yeah.

s33
00:02:25.040 --> 00:02:32.319
So anyway, with that out of the way, uh let's talk about the first point which is texts don't matter.

s34
00:02:32.319 --> 00:02:38.000
Now, a lot of people say that it doesn't matter what programming language you use, what framework you use.

s35
00:02:38.000 --> 00:02:41.280
You can just ask your agent to build you anything and build it is able to do it.

s36
00:02:41.280 --> 00:02:53.120
And 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 codebase with solid abstractions,

s37
00:02:53.120 --> 00:03:04.080
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.

s38
00:03:04.080 --> 00:03:06.400
And the reason is like it's very simple.

s39
00:03:06.400 --> 00:03:15.040
the agent doesn't need to reinvent the same like wheel every time it tries to add a new feature or it doesn't need to introduce new patterns.

s40
00:03:15.040 --> 00:03:18.879
It will just essentially follow existing patterns.

s41
00:03:18.879 --> 00:03:27.920
And when it comes to like what you choose, I feel like it kind of doesn't really matter as long as you have a code base that is properly structured.

s42
00:03:27.920 --> 00:03:34.799
But like my go-to choice today is one tan stack libraries for anything when building on the web.

s43
00:03:34.799 --> 00:03:38.799
And if you're building anything content related, I would say definitely go with payload.

s44
00:03:38.799 --> 00:03:41.440
Solid experience, great abstraction.

s45
00:03:41.440 --> 00:03:50.640
I went down like a big rabbit hole of like comparing CMSS at some point because I don't believe that I should uh build it from scratch even though I can.

s46
00:03:50.640 --> 00:03:51.920
But again, who knows?

s47
00:03:51.920 --> 00:03:53.760
Maybe the future will change.

s48
00:03:53.760 --> 00:04:01.439
But yeah, and that's kind of like the main first item that I kind of ran into.

s49
00:04:03.680 --> 00:04:16.160
When you use like a lot of SAS products out there that you actually love that you use every day, when you're a user, there's like a lot of things you don't notice, but when you actually try to like replicate an experience,

s50
00:04:16.160 --> 00:04:21.680
you quickly find out how much care and thought goes into different flows.

s51
00:04:21.680 --> 00:04:29.360
So like something as simple as oh I want to be able to send an email or to publish something.

s52
00:04:29.360 --> 00:04:38.080
You can easily do it by having like a good old you know just like server side rendered app with like forms that you submit.

s53
00:04:38.080 --> 00:04:46.880
But if you try to build something that is going to be used every day that you will reach for a lot you're like oh it shouldn't feel that way.

s54
00:04:46.880 --> 00:04:55.199
And there are kind of like a bunch of patterns that I found that agents don't typically do unless you explicitly ask them to.

s55
00:04:55.199 --> 00:04:56.800
And this is my list.

s56
00:04:56.800 --> 00:04:58.720
So we'll go through them one by one.

s57
00:04:58.720 --> 00:05:00.560
And the first one is like autosave.

s58
00:05:00.560 --> 00:05:08.479
I found that if like let's say I'm building some form of document editor, autosave is kind of like a table stakes feature.

s59
00:05:08.479 --> 00:05:22.479
So 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

s60
00:05:22.479 --> 00:05:28.639
so that you can let's say if as you're typing you're able to type and then it just automatically saves.

s61
00:05:28.639 --> 00:05:39.360
And 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.

s62
00:05:39.360 --> 00:05:47.199
So it's kind of like this these two layers that kind of guarantee that whatever it is that you're working on is just not going to be lost.

s63
00:05:47.199 --> 00:05:55.360
Now you can also go a step further and to add like real-time collaboration so that you can have like concurrent edits.

s64
00:05:55.360 --> 00:05:59.280
And again, my agent didn't struggle at all with adding the feature.

s65
00:05:59.280 --> 00:06:06.800
It was like, I don't know, asking about it, reviewing how it would work, and then once that's done,

s66
00:06:06.800 --> 00:06:10.160
just 700 million tokens later, I had real time.

s67
00:06:10.160 --> 00:06:18.160
So, I would say in general, this is the first thing that I find agents just don't do well from a product experience perspective.

s68
00:06:18.160 --> 00:06:22.639
Another pattern I found that agents completely forget to implement is optimistic updates.

s69
00:06:22.639 --> 00:06:35.199
So rather than showing your users a bunch of loading spinner whenever they're taking any action, you essentially show them the success state you know optimistically and in the background you're going to sync whatever change they made.

s70
00:06:35.199 --> 00:06:43.199
Now if the sync or the operation fails for whatever reason you just roll it back and then tell them like oh the operation work.

s71
00:06:43.199 --> 00:06:47.120
Now of course you shouldn't blindly have optimistic updates for everything.

s72
00:06:47.120 --> 00:06:54.800
There are some scenarios where you want to show the user a loading spinner and you're going to wait to check that everything worked properly.

s73
00:06:54.800 --> 00:07:05.280
But in general, having optimistic updates makes the overall experience feel significantly faster, much snappier, and it will just feel much more instant.

s74
00:07:05.280 --> 00:07:11.599
So pretty sure you can just ask your agent like, "Hey, I would like to implement optimistic updates where it makes sense.

s75
00:07:11.599 --> 00:07:12.560
Let's come up with a plan."

s76
00:07:12.560 --> 00:07:14.960
And it will tell you all the areas where it makes sense to do.

s77
00:07:14.960 --> 00:07:18.720
Again, it's like it's not difficult for the agent to build it.

s78
00:07:18.720 --> 00:07:21.840
You just need to ask and know exactly what to ask for.

s79
00:07:21.840 --> 00:07:27.840
Now, an extension of optimistic updates, in my opinion, is giving users the ability to undo certain actions.

s80
00:07:27.840 --> 00:07:36.639
Now, for example, if you ask your agent to implement the ability to delete records, what it will typically do is it will give you a delete button.

s81
00:07:36.639 --> 00:07:42.800
You click it, might show a confirmation dialogue, you hit confirm, and then it will actually do the deletion.

s82
00:07:42.800 --> 00:07:48.160
But a much nicer experience is actually allowing the user to undo that action.

s83
00:07:48.160 --> 00:07:58.160
So they hit delete, you immediately remove the item they want to delete from the UI, but you tell them like, hey, you have like a couple of seconds where you could change your mind.

s84
00:07:58.160 --> 00:08:03.120
And if they don't do anything, that means you actually want to delete a thing.

s85
00:08:03.120 --> 00:08:05.919
Then you actually implement the operation.

s86
00:08:05.919 --> 00:08:09.199
Otherwise, if they hit undo, you just bring back the change.

s87
00:08:09.199 --> 00:08:13.599
So it's kind of like you do the operation in the background as well.

s88
00:08:13.599 --> 00:08:20.080
It's just kind of a delayed action which kind of ties into the next point which is archiving.

s89
00:08:20.080 --> 00:08:31.280
You should tell your agent you want the ability to archive records and be able to unarchive them because sometimes you want to hide something from the UI completely or let's say from search results

s90
00:08:31.280 --> 00:08:37.680
and archiving will be the way to do it and you shouldn't force your user to be like well if you don't want to see this you have to delete it.

s91
00:08:37.680 --> 00:08:41.440
and a much better experience is just the ability to walk out records.

s92
00:08:41.440 --> 00:08:45.519
So I think it is a pattern that should definitely exist.

s93
00:08:45.519 --> 00:08:47.200
Another big one for me is URL state.

s94
00:08:47.200 --> 00:08:54.480
you should ask your agent to persist in the URL whenever it makes sense of course and it's so useful because whenever you have let's say a list of records

s95
00:08:54.480 --> 00:09:12.560
and you want the ability to filter or sort them and you just have a bunch of like conditions maintaining these things in the URL makes it trivial for you to give them to someone else and then let's say another team member is just going to be able to see exactly what you want them to see now another

s96
00:09:12.560 --> 00:09:21.680
small detail that agents don't implement out of the box is infinite scroll I don't want to be clicking on load more over and over and over or like a next page button

s97
00:09:21.680 --> 00:09:38.160
as I scroll I should just get the data I shouldn't need to click next page and then in the end I'll just see that oh I've reached the end it's a very minor thing but also when you use something every day I think it makes a huge difference now another pattern I found that made the output significantly

s98
00:09:38.160 --> 00:09:50.160
better is telling the agent explicitly to use existing pages as references when it comes to the UI the data fetching and how it works works and how the thing is overall structured

s99
00:09:50.160 --> 00:09:58.560
and that made it possible for me to essentially define what good looks like once and then just reuse it for more features.

s100
00:09:58.560 --> 00:10:07.680
Now to be completely honest sometimes even when you tell the agent like hey use page X as a reference sometimes it just doesn't follow it.

s101
00:10:07.680 --> 00:10:12.240
I don't know if models like get dumber sometimes but sometimes it does happen.

s102
00:10:12.240 --> 00:10:23.040
But overall, I would say that my success rate is higher whenever I tell the agent to like, well, use an existing page as a reference because you also just end up with a more consistent experience.

s103
00:10:23.040 --> 00:10:31.040
So like as you're using your app, you're like, oh, this just matches the other part of the app if they both share like the same concept.

s104
00:10:31.040 --> 00:10:43.519
So like if two parts of the app are essentially lists of records that you can create update and delete and like list well both of these parts should be pretty much identical.

s105
00:10:43.519 --> 00:10:54.399
This list kind of brings me to my next point which is whenever you have opinions about something they should be packaged as agent skills and then this way your agent whenever it's building something it will actually follow

s106
00:10:54.399 --> 00:10:55.920
those skills pretty closely.

s107
00:10:55.920 --> 00:11:01.279
And as I was building all of our internal tooling, I found myself reaching for three Asian skills.

s108
00:11:01.279 --> 00:11:03.600
Uh two of them are related to design engineering.

s109
00:11:03.600 --> 00:11:11.680
So one made it easier to have better UI, better typography, better layouts as well as like better error messages in general.

s110
00:11:11.680 --> 00:11:18.800
And the second one was a set of design engineering skills that made it easier to just have better animations and other things like that.

s111
00:11:18.800 --> 00:11:21.839
And then last but not least is the railway Asian skills, of course.

s112
00:11:21.839 --> 00:11:29.040
So like everything that I built for us internally at railway runs on railway of course like everything.

s113
00:11:29.040 --> 00:11:34.000
So like buckets, databases, the app itself, the real-time server, everything.

s114
00:11:34.000 --> 00:11:42.399
And for the agent to effectively work with railway and be able to deploy everything, you just give it the Asian skills and it was just able to do it.

s115
00:11:42.399 --> 00:11:53.680
And yeah, so like once you have all of your Asian skills and everything, in my opinion, the final step and I think this the most important step is verification.

s116
00:11:53.680 --> 00:12:02.399
So the agents typically whenever you ask it to build something, it's going to be like, okay, I implemented the feature, build passed, test pass, all good, right?

s117
00:12:02.399 --> 00:12:10.079
But what I found is when you actually try out what happens, you sometimes end up with just like a very broken experience.

s118
00:12:10.079 --> 00:12:19.600
So once you have like a verification loop in place, it's like a night and day difference because the agent you can literally see it be like, "Okay, I built this thing.

s119
00:12:19.600 --> 00:12:20.560
I tried it.

s120
00:12:20.560 --> 00:12:21.279
It failed.

s121
00:12:21.279 --> 00:12:22.639
I'm going to fix it."

s122
00:12:22.639 --> 00:12:23.839
And it just keeps going.

s123
00:12:23.839 --> 00:12:26.320
And then in the end, it's like, "Okay, I fully tested it."

s124
00:12:26.320 --> 00:12:31.279
And I felt this breakthrough with computer use once it got really, really good.

s125
00:12:31.279 --> 00:12:40.160
And now everything 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

s126
00:12:40.160 --> 00:12:47.920
and use it by actually running infrastructure and to test things end to end and the agents are very capable of doing this.

s127
00:12:47.920 --> 00:13:00.320
You just have to tell them and once you have all those pieces I would say you will end up with solid internal tools that you can build quickly that work properly and work in a consistent way.

s128
00:13:00.320 --> 00:13:00.880
And that's it.

s129
00:13:00.880 --> 00:13:04.399
This was my list of principles that I use whenever I'm building any internal tools.

s130
00:13:04.399 --> 00:13:13.680
Hope you found them useful, but more importantly, that you're inspired to build your own internal tools that feel good, that are polished, and spark joy.

s131
00:13:13.680 --> 00:13:17.440
And I hope that you too can become your company's SAS layer.

s132
00:13:17.440 --> 00:13:22.560
And with that, thank you so much for watching and I'll see you in the next
