The Calm Before The Storm
Welcome to Slow and Steady, the podcast where you get to follow along as we build products in public. Each episode gives you an honest peek into our lives as we share our struggles, our wins, and everything in between. I'm Benedicte, and I'm feeling calm.
Benedikt:And I'm Benedikt. Today is August 11. This is episode number two forty eight, and I'm feeling excited.
Benedicte:Aye, aye, aye. I might be calm before the storm as I'm Yes. Getting married on And I still have to alter my dress. But that will be fine. The friend's coming over tomorrow.
Benedicte:So I am still calm.
Benedikt:Okay. Yeah. Well, I guess that I hope that just continues to persist until after the weekend is over.
Benedicte:I hope so. I hope so. I've been calling in the cavalry. I have a good feeling.
Benedikt:Very good. Very good. Am looking What makes forward me excited? To Well, for one, I will be attending your wedding, so that makes me excited. Excited.
Benedikt:That makes me excited. No, not really, but makes me excited. And I got a super early flight. My flight is at seven a. I have to leave the house by five or something like that.
Benedikt:But it was half the price compared to the one in the afternoon, so I was like, I just do it, I guess. And I think the other one would have been a little bit too late because the airport in Oslo is pretty far out, isn't it? At least it looked like
Benedicte:It's like an hour.
Benedikt:Yeah. So it's a good idea. You take only one. Anyway, so excited about that and excited about the work I've been doing lately. So, yeah, we could talk about that.
Benedikt:What have you been up to, though?
Benedicte:I maybe should have sounded excited too. At least proud because welcome to Slow and Steady. That is no longer about digital stuff. Almost don't talk about programming anymore. Because I made a stool, a box, and a chair last week.
Benedikt:Nice. And
Benedicte:you would think like, how proud can you become?
Benedikt:Out of wood or
Benedicte:Out of wood. Hard part? Hard part. It was out of wood. It was a beginner carpenter, or like woodworking class or carpentry class.
Benedicte:And I was like how proud can you become? It turns out you can be very very proud like there are photos of me coming in and showing Ola and I'm just all smiles and I think everybody in the class at the end of the week were like, we are invincible. Like, we can make anything at this point. And we were so proud of our our makes, our builds. And also like you wanted to show it off like look at what I've made, you know, I felt like I was my daughter, you know, how you know how kids make things and they're like look look look look like look at what I made, look at what I made, look at what yeah Exactly like that.
Benedicte:But I thought I was gonna work in the afternoons because it was the class was only from ten to three, but turns out this developer's body is not used to standing for, you know, five hours working, so I was pretty exhausted when I came back, and also like brain work, like getting all of the cuts correct and everything, but so worth it and just highly recommend. But yeah, let's hear about your computer work, which makes you excited.
Benedikt:Yeah, I cannot believe that I was able to make this task exciting. So recurring theme or like ongoing theme, we're working on a new theming system for user list, and that also includes improving how our emails well, not our emails, but emails sent through Userlist render in Outlook, which is a topic that we have been trying to avoid for forever. They were rendering sort of okay ish, but once you got a little bit fancy, everything started to break down. So one of the goals for the new theming system was also to fix all of those issues, and I've been dreading this for forever. I mean, you can probably tell that it took us this long to spend some decent amount of time on this, but I've been dreading this because it's not fun.
Benedikt:It's annoying to test because there are some tools out there. We're using testy at where you can basically paste your HTML and then it will render it on different versions of Outlook and all the other email clients. And then you compare, and then you're like, Oh, it looks shitty. I need to fix something. And you fix, and they copy It's a tedious process.
Benedikt:It doesn't make a lot of fun. And Outlook, at least the old versions, is horrendous at rendering HTML email. Fun fact: old Outlook versions are not even using Internet Explorer used to be a thing. We kind of forgot about that, right? And you'd think that Outlook is just using old versions of Internet Explorer to do the HTML and rendering.
Benedikt:But you'd be mistaken. It's actually the Word rendering engine that you're forcing into rendering HTML email.
Benedicte:The Word? Like the Word Yes,
Benedikt:Word processor rendering engine is the thing that's rendering HTML email. And as a result of that, you have to do the weirdest stuff to get spacing correctly, buttons in place, all of that stuff.
Benedicte:Would have talked to the engineer that decided to use Word as the rendering agent at the time where there were browsers, even though I don't know.
Benedikt:Guess they thought like, this is electronic emails. You write the analog emails in Word. So I don't know. Like, I honestly don't know.
Benedicte:This would be, I mean, podcast
Benedikt:ID for user list
Benedicte:is just, I mean, you could have seasons of a podcast that just talked about different, like, email stuff, like everything from Outlook, old Outlook rendering to how all of the, like, you know, how the sending actually works, like, do they got get lost, spam, whatever those things are called, like how do the the spam rating. Right. Oh my. This is
Benedikt:this this
Benedicte:this this this
Benedikt:this who made that who made that decision back in the day.
Benedicte:Yeah. I would listen to I would listen to a podcast like that because I imagine there's gonna be so much, like, web history if you start
Benedikt:Mhmm.
Benedicte:If you just look yeah. If you make episodes of anything email related, you're gonna be finding these stories from I don't know. I think it could be super interesting. Right.
Benedikt:Yeah. And then
Benedicte:feel like this could be an
Benedikt:episode of 99% Invisible. Talking about email. That type of production, just about the history of email. That would actually be Yeah, I like that idea. I'm not sure I'm the one to do it, but I liked Someone, the
Benedicte:this is a free idea. I you know, Benedicte and I would listen. Benedicte, of course, because he he works in email, but I would listen just because I find it fascinating, and I think it will be a proxy for so much technology history.
Benedikt:I'm not even sure I want to say this is a free idea. Like, if you think about doing it, let us know, right? Maybe we can figure something out in the user list context because I feel like that's also a good marketing idea.
Benedicte:Could be
Benedikt:a good user list podcast, actually.
Benedicte:Well, whoever makes it first. Right?
Benedikt:Don't say that. Let's cut all of this. Let's cut all of this.
Benedicte:Let's cut all of this out. But, anyway, back to you were trying to get emails to render correctly in Yes. The I was dreading word renderer. Exactly.
Benedikt:I was dreading it because it's a mess, right? So I've been well, we we got to a point where I figured, like, we got all of the other plumbing in place. I should figure out, we have some new In the process of revamping the structure of the themes and everything, you also will include a new set of themes for users to pick emails. For And I figured this was now a good time to start implementing those new themes because they work a little bit different and the old ones look a little bit different. So that was the first step.
Benedikt:And in that process, of course, I had to check that they look good in Outlook. And of course, they didn't initially. So I've been trying a couple of things to fix that. And one of the things you can do in Outlook is they have this XML language thingy called VML, like vector markup language or something like that, similar ish to SVG, I guess, but from back in the day. And you could do some fancy stuff like rect with rounded corners or a custom shape and stuff like that.
Benedikt:So you can get some button looking thingies in there, but you have to write some custom HTML and stuff like that, and of course then that doesn't render well in other browsers. So there's also this thing called a conditional comment, which is also an Office or Outlook type thing where you embed HTML comments with a special syntax so it becomes like an if else type of thing. So you do the comment and then do VML in there and then the actual button in raw HTML and so on and so on. But that's still super tedious to write, especially if you want to have a consistent system where all of the buttons get rendered properly. There are other tools out there.
Benedikt:For example, Mailchimp has its own markup language. It's called MJML, Mailchimp Markup Language, where we basically write sort of HTML but with custom components. So you do an MJButton or an MJImage. And internally, it's basically doing the same thing, like rendering both the HTML version and the VML version or an elaborate table structure. So I looked at that and weighed the ideas, but I didn't like the idea of having to write a custom markup language.
Benedikt:So what I ended up doing eventually Maybe let me take a step back. One other thing we have to do while processing the emails is inlining CSS styles onto the element into style attributes. I think this is because of Gmail because Gmail strips style tags from the emails before rendering it, so you basically have to inline all of them. In that process, when we render the emails on our side, we basically render them as a string. But for the inlining, we have to take the string, create a DOM from it, like actually parse the HTML, and then walk through and apply the styles and write the attributes and then serialize back to HTML.
Benedikt:We were using a library for that or still are using a library for that. There are two libraries in Ruby. One called PreMailer, the other one is called Roadie. They basically do this for you, give them the HTML with the styles, it'll just merge it. And then what we are also doing for stuff like click tracking and open tracking is basically do the same thing again.
Benedikt:Parse the entire tree into DOM, then look at all the links, take all the links, wrap them in tracking links, and at the end, inject the tracking pixel into the DOM structure as well and then render back to text. So one of the things I was looking at was, we're doing the serializing twice, parsing twice, serializing twice, that's kind of stupid. We could just do one pass. So that was one idea. And then the other idea was for the stuff like, this is a button and this is an image and all of that special processing for Outlook, I was like, couldn't we just control this via CSS?
Benedikt:Be like, This class For example, all your buttons have a button class on it. Couldn't you just tell the CSS that this is a button and this should render as a button in Outlook? So I made some experiments in combination with the inliners because they already work with the CSS. They parse the CSS and stuff like that. And I figured out a way where we can basically have our custom CSS attribute.
Benedikt:I popped it for user list appearance. And we would look at that attribute, and if it's present, then we changed the rendering of the markup in the HTML. And it works. It just works. And I was super excited about that.
Benedikt:But then trying to figure out the ergonomics with those existing two libraries was a little bit cumbersome. And at some point, I was like, How hard would it possibly be
Benedicte:to Famous write our
Benedikt:Yeah, to Famous last last words. I mean, words were one and a half weeks ago. And I think this is a project that I wouldn't have done without AI Help, but with AI Help, I was able to get pretty far. And turns out, the implementation we have is more flexible, more powerful, can do more stuff while being twice as fast as the existing fastest solution and using less memory than the fast solution. And that got me so excited.
Benedicte:Open source it. Source it.
Benedikt:Because we're doing more work faster with less memory usage than the two libraries out there. And yes, I think we're going to open source it. I found a good name for it. There was already a Ruby gem with that name, but it was unused. So I reached out to the owner, and they were kind enough to transfer it to me.
Benedikt:And now it's not just a matter of finishing it up, then we'll probably probably not going to make it this week, but once I'm back from vacation, I will finish this up, package this up, and release it. Because I genuinely believe it's the better solution just based on the raw numbers. Mean, maybe I'm still missing something, but so far, it looks like it's doing the job. I benchmarked all three of them, and the results are basically the same in terms of the output of the HTML in the end with the inline styles, and as I said, faster and more memory efficient. So yeah, excited about this.
Benedicte:Could just be that you're been thinking about this problem, you know, longer and more than a lot of Ruby developers. Yeah, I think for many, it's just like, oh, they're gonna send some one off transaction emails that need something and they reach for They're not using it at scale. Right? Well, coming from the at scale perspective and also something that is the domain. I mean, you kind of are the domain expert
Benedikt:Yeah, think the ad scale part is the key here. We are sending a ton of emails and we're doing this basically for every single email that we send out. And I already made some As I said, there are two versions, like two libraries out there, and one is officially unmaintained. So we were not using the unmaintained one for the longest time until I think last year benchmarked them. And the unmaintained is 10x more memory efficient than the officially maintained one, and I think two, three times faster.
Benedikt:So at some point last year, we switched just for performance reasons, but now the new implementation that we're rolling out ourselves is even faster than that. So I'm excited, as I said earlier, for multiple reasons.
Benedicte:I'm happy for you.
Benedikt:It's a cool project to work on. As I said, I did not expect making stuff work in Outlook to be a fun project, but here we are. I'm actually enjoying this quite a bit. I'm learning a ton about CSS itself. I've been browsing Firefox source code on GitHub last week just to get an idea.
Benedikt:Or even browsed WebKit source code yesterday as well, just to get an idea how does this work in browsers and how do they model the stuff. And then having Claude help with that, help with the actual writing of the code is actually super helpful as well. So yeah, it's a fun project. I'm spending probably way too much time on it, but I hope it's worth the effort and we get something cool out of it that we can use ourselves and then share with the community. So yeah, excited.
Benedicte:Also, you deserve to have some fun with these things. I feel like you have earned a position to go about it beyond
Benedikt:way too much fun.
Benedicte:But, I mean, it's your company. This is exactly why, you know, this is the perks.
Benedikt:I guess. Yeah. I can decide
Benedicte:made to the choices that you've made. Like, you don't have to convince a boss that this is a 100% the best use of time for the business value. I think you having fun is definitely of business value to the company because Maybe. That
Benedikt:Yeah. Maybe
Benedicte:not all the time, but like, you know, sometimes giving yourself less space to like, explore and have fun makes it worthwhile, like being the owner and operator of something.
Benedikt:Right. Yeah. Yeah. I guess you're right about that.
Benedicte:Even if it's taking more time than you feel like it should take or whatever.
Benedikt:Yeah. Yeah. I hope that the efforts will be worth it in terms of what the results will be. I'm still fairly confident that it's a good investment, even though it's been two weeks and I didn't but plan to take this it's going to be a solid solution. I'm excited about that part.
Benedicte:Do you think people on older Outlook just get used to crappy emails?
Benedikt:I guess. That's the assumption that we've been operating on for the longest time. And for the most part, I also think most of our customers, their customers are not necessarily on Outlook. But every once in a while, we get some complaints about, This email looks completely different than Outlook. And we're like, Yes, because it's Outlook.
Benedikt:But still, mean, they will never be exactly the same, but if we can get it closer or have them look less shitty, I think that's already a win.
Benedicte:Absolutely. I was just wondering, like, if there are, you know, people out there just thinking that all marketing email is crappy looking. Yeah.
Benedikt:That's, because
Benedicte:they're using an email client that just makes all of them look crappy, so they just assume that's the way it should be, Or if they realize it's their email client.
Benedikt:I guess some do, some don't. I don't know. But yeah.
Benedicte:Yeah. So I've also been working on email kind of. So we have merged in a recover cart kind of feature. See a lot of our customers come in and almost complete an order. The last step is giving us your credit card details.
Benedicte:Mhmm. And a lot of people then don't do that, but then we see and we don't have like a prop or kind of card system. So when they come back, they have to redo their whole order. We see a lot of I've seen a lot of people kind of doing, getting to what we call a pending state, maybe two or three times, and then they complete an order, and they're Mhmm. Like, they're ordering the same bike every time.
Benedicte:So now we're we have a job that just that every hour goes through all of the pending and send them an email with a link that they can click and, like, add their credit card information. This is obviously far from where it should be, but hopefully it's a step also to recover the ones that don't come back. So a lot of people come to that stage and we can see that it's you know real emails, real people, and then on that last step they're kind of become a little bit hesitant. It also starts a so we do this by using our new support system. So it starts a ticket.
Benedicte:Like, it sends an email to the person. But then if nothing happens, our operations and salespeople can then follow-up with a manual follow-up email. If they answer, it gets in on that ticket. So hopefully that's gonna help a little bit in sales, cause that every sale counts. So that's in production almost because it's in production but it's only logging now because we don't want because since the system is a little the data model here it's a little iffy Sometimes people then go back and order and complete, and we don't wanna send them recover cards, you know, because they have a pending order and then they have a completed order.
Benedicte:So there's some logic there, and I just wanted it to go through for a couple of days to just manually check that we're not sending these recover carts email to people who have completed, which is so easy to see as a human. You just like look at the orders and you're like, yeah, that's the same email, that's the same. And for reasons it's not as easy in code.
Benedikt:Right, right.
Benedicte:So we're gonna let it dry run for a little while and then we're gonna hook it up to the support system. So that's all I've done basically since last time we spoke. Oh well I made a chair a box. You made a chair and And a
Benedikt:And a stool, very good.
Benedicte:But it's exciting. So this is work that Ula started and then I completed, which is a fun way of doing things. Know, I get to think about the edge cases and and all and of that fun, or me and the AI get to think about edge cases and and everything. And now that we made some email, different email things, we were gonna need a little bit of a re architecture on how we do the queues and the jobs and stuff like that. Because I am quite new to like queue and jobs and that way of thinking.
Benedikt:Mhmm.
Benedicte:But luckily, we are not the largest org organization. So it kinda works even if Right. I don't do it in an optimal way.
Benedikt:Did you consider doing this in your ESP?
Benedicte:Yes. So I was back and forth, both could have worked. The reason why I want the ticket route is because I think a lot of people won't do anything and will not reply or complete. So then it just stands there as an open ticket so our sales folks can be more proactive.
Benedikt:Right.
Benedicte:You know, so they like, for and then maybe we will get more tighter and automated processes of like we'll send another one after seventy two hours or we'll do, you know, we could have multiple steps. But for now, our volume is fairly low and we and this is a very new thing we're trying out. So I wanted it to be mostly manual. So we'll send the first one automatically, and then it's up to up to our our salespeople. So our sales like, we have operation.
Benedicte:There's one person. So she sits at the workshop and she has quite a good overview. Sometimes people even stop by to ask questions. You know, they might have called. So I think, like, as long as we're at this size, like, she kinda she has information that that the system might not have, so she can make some educated guesses also.
Benedicte:Because we have influxes of people who should not get our bikes. So we have every year, we get every spring, we get a bunch of people that wanna do for do ara, like, delivery and stuff like that, then they wanna rent a bike from us, and that's not Mhmm. Allowed under our terms of service, And we have kind of a human filter. We can look at the emails, and we we were fairly certain who who those people are and who they're not. So if I send, you know, a recover cart, we send an automatic recover cart to them, and then, you know, she goes in, she can say, oh, but, you know, you shouldn't because you you you won't be allowed to get one of our bikes.
Benedicte:Or it could be somebody's, like, husband or wife trying. There's all kinds of like little nuances. So that's why we didn't do that for now. But then I started thinking, does it matter if somebody gets like three abandoned cart emails even if they've completed one? Maybe not.
Benedicte:But we'll start doing it this way and see what we learn.
Benedikt:It's I'm sure it's already an improvement to not sending them.
Benedicte:It's an improvement from nothing. Yes. Yeah. Because we've been trying to do it a little bit manually, but it kind of gets lost. Like, can look at the order list and you could like pick out who should get it, but you know, that doesn't happen.
Benedicte:So at least the system can kickstart, kickstart an open ticket, then it's easier for, you know, for for the people or Ingrid who does does this for Ingrid to like look at her open tickets and be like, oh, yeah, I should follow these people up Yeah. Or
Benedikt:Makes sense.
Benedicte:And then close the tickets if it looks like it's people who who she shouldn't do anything more with because they they're never gonna be completing this disorder or shouldn't be completing this order. But we're tidying it up, know, tidying one little chunk at a time and adding some features where it's needed.
Benedikt:Very cool. Yeah. I like it.
Benedicte:And we're using it there there, which is Freck something. It's he's like a big guy in Laravel. He has he has created many of the systems that I've liked. They're usually stable. So when he came with out with a support ticket system, was like, we're just gonna Yeah.
Benedicte:Use that's on European soil Soil. And there's some AI sprinkled in there, but it's not like AI hype.
Benedikt:Right. Yeah. Makes sense.
Benedicte:Yeah. Systems. And I like the name. So it's there, there, like, there, there. It's gonna be fine.
Benedikt:Yeah. Yeah. That's good. That's a good name.
Benedicte:And it fits with the wee brand. The brand of the company.
Benedikt:Right. Yeah. Makes sense. Makes sense. I like it.
Benedicte:Yeah. I think that's about it. Did I do anything else? Did I know time something else? No.
Benedicte:I did not. Yeah. This is my focus for the fall. I'm gonna be working, which I've said on this podcast for many years now, slow and steadily.
Benedikt:You're doing a good job, I guess.
Benedicte:Yes. Doing a little bit at a time, going for walks, doing more woodworking, and just keep on keeping on. That's the philosophy. Finally, might be able to do it.
Benedikt:Cool. Well, I guess that then wraps us up for this week or actually for the next couple of weeks because I will be on vacation the next two weeks.
Benedicte:And I'll see you on Saturday and everyone else on the interwebs.
Benedikt:Yep. See you around.
Benedicte:Bye. Bye bye.
Creators and Guests
