BrandGhost

I Let Cursor Build My Website... Here's What Happened.

In this video, we'll look at using Azure Functions to send emails via SMTP (Gmail in this case) for a question submission page on my Blazor website! Code Commute viewers can now submit questions to get answered on the channel!
View Transcript
In this video, we're going to be looking at using Cursor to Vibe Code an email submission form for my website. My name's Nick Cosantino and I'm a principal software engineering manager at Microsoft. In this video series that I've been putting together, we're basically vibe coding using different AI tools to help with my other site called Code Commute. Now, if you haven't heard about Code Commute, that's my other YouTube channel where I take user submitted questions and I try to answer them in a vlog format when I'm driving to and from work. So, if you haven't checked that out yet, you can check that out right up here. I think it's an awesome opportunity to send in questions and that's exactly why I wanted to put this feature together on my site. So, if that sounds interesting, remember to subscribe to the channel and check out that pin comment for my courses on dome train. Let's go check out the finished product and then we're going to work backwards and see if we can essentially replicate this in a way that cursor can understand. And that way, instead of going through all the pain that I went through originally, we can see if we can do this a little bit more optimally and refine the props. So, let's head over to codecommute.com. This is the website that I put together in the previous videos in the series. And the new page that we're going to be looking at is this contact form. So, super pretty, right? Nice and elegant. Submit your question. You can check this box to do it anonymously, right? And then, so if you do it anonymously, you don't have to submit the social platform or social handle or your name, but uh that way if people want to, then they can provide that information. But there's no pressure. This is hosted on GitHub pages. So, it's basically a client side. It's a static page, right? So, I can't just send an email from this. I have to go use an Azure function. Well, doesn't have to be an Azure function, but I use stuff in Azure, so it's going to be an Azure function. I need to be able to have cursor well, I've already done it, but we're going to make cursor go do an Azure function as well as these front-end changes. What I am proposing that we do to make this work is I'm going to take this. I am going to basically put that up on this screen over here. I am also going to have up on my screen the commit, but I'm going to hide the details of what it did because I want to try and simulate this like we're doing it from scratch and the only thing that we're going by for the most part is like this finished product. We have some idea in our mind what we want. In this case, I have the finished product, but for you, you might be looking at some other website and you're like, "Wow, that's a cool feature that I'd like to have." or looking at an app and saying that's a cool feature you want to have. So I think this is interesting practice to say what parts do we want to call out as features for cursor or whatever tool that you want to use. What things do we want to call out as features for it to go work on? I want to save us a little bit of time though and have the git commit up because this way that we can shortcut some of the headache that I had along the way and that way it'll go a little bit more smoothly. So, I'm proposing I'm going to write up the features and the changes. And from there, we can see if we're going to do this as a oneshot in cursor, which maybe is a little bit ridiculous. I don't know if it'll work. Or if we see that there's some logical grouping and progression, we can try splitting that up. I'm a little bit more in favor of that one because I've always found that just giving too much to agents is just a nightmare. So, let's go ahead and say that we basically need a new contact screen. So create a new contact screen and the next part will be the features that we want on here. So an optional anonymous field and I will say if the anonymous field is set then only a question is needed otherwise we want name entry we want social media platform and we want social media handle. Okay, this is what we have on this screen. The text that's on the right, I don't really care about that. It kind of did that on its own. The first time I didn't tell it to do a word counter. Maybe that's a cool feature. So, we can say like include a word counter. And I also I guess I need to mention we need a question box. I kind of forgot that. One thing that I remember when cursor was putting this together originally for me did truly treat this like a contact or like a feedback page. So all of the language and text and stuff was like, "Hey, like we're here to support you." And like that's not what this is. So I need to be a little bit more crisp about that. I think it's not just a new contact screen. Create a new contact or like question submission page for users to submit questions to be answered on my YouTube channel, Code Commute. And I'm trying to be a little bit more specific with the language this time than when I did this originally because I just said make a contact page and it's going to have like a question and stuff like that. But I'm hoping if I say my YouTube channel and I call out code commute instead of it saying like we are here to support you, it will say something like submit to my YouTube channel. So we'll see if it's able to pick up on that. Otherwise on here, I think that might be it that I care about. Like I said, this box on the right hand side, I don't care how the how the things are styled. I don't really care. So, we'll see. I think that's probably good enough. But the next part to this is that we need to be able to say that we need to submit the form, which will send an email to the and I'm going to call out an Azure function that we'll need to make. And maybe I don't know like I I figure in my prompting sometimes I say like we need to do this and other times I say like you need to do this to instruct the LLM. I actually don't know if one of those works better in my experience. So my language you might see like I kind of mix it. Sometimes when I'm telling it to correct itself I will say like you need to go do this. But when I'm talking about designing things I say we I don't really know if it makes a difference. We'll try that. And in my mind, I'm wondering if that's like part one of the prompt cursor. When I did this originally, I gave it less detail, but I was more broad and I did say an Azure function and it actually built both at the same time pretty well. So, we might be able to combine this first part of the prompt with the next part. But I am probably going to consider splitting it up. So, we can't see the Azure function of course from looking at the web page. But if we go look at the commit, some ideas will hopefully come back to my mind. So originally I said I want to send it through Azure. But it picked the service from Azure that it's going to use. So let's say um add and how do we want to call this for handling the Azure function? We need a new project in the solution. I should turn on word raprap here. Let me go and do that. Let's add a new project to the solution for hand or handling the Azure function. The Azure function will submit an email from the front end. The thing that I want to call out is the technology we're going to use. So that will use SMTP. That means that for me I can use a Gmail address because the traffic volume will be low and instead of having something like Send Grid or something else through Azure that's a lot more complicated. It's going to cost money like I'm not sending like hundreds thousands tens of thousands of emails. No, it's going to be the odd person that comes to the site and wants to send something in. The Azure function will use SMTP. And what else do we want to say? I'm kind of glancing over at the right hand side to see if there's things that come to mind for me. So if you're not familiar what that is, basically being able to load things from uh this is sort of the interface or the abstraction that we have in C especially in ASP.NET Core, but it could be from app settings. It could be from environment variables, which is the next part I want to add in. It tried to originally build out the deployment and stuff for you can actually see that there's like a deployment readme file in the git commit, right? So I'm going to say I will manually deploy the function from Visual Studio to Azure. So I don't know why for me personally because my Azure functions that I'm using like across all of the projects I use I rarely use Azure functions I am not personally yet comfortable with like deploying an Azure function in my CI/CD. So whenever I make a change it's usually just like in Visual Studio publish it right there. I don't know why. I think it's something that I pay less attention to on the surface. Like I would know if my server was broken for something or if I broke the UI for something I'm building. But I feel like Azure functions I just I feel like I have less visibility into which is just a me thing. I'm going to ask it to not do a deployment or suggest I'm going to deploy it manually and see what it does. So it doesn't have to go touch my deployment scripts. What else? I think I missed something up at the top. I just remembered sure there's an icon for the contact nav item in the top bar. Okay, so we'll do that. Trying to think if there's anything else for the Azure function though that I need to call out. There's no test written on this. That might be something that's good, but I haven't set up like a testing pattern in here yet. Um, there was a gotcha when I worked through this the first time, but it's solved in Azure itself. And that's going to be cores. When I had this all up and running, it was failing from the web page even though I could do it locally to the Azure function. But in Azure, I can toggle cores. So, I will walk through some of the Azure stuff as well, but I want to get the code generating. So, we'll see about that. The other thing that it did is it actually did um I I told it to do a directory like a central package management. Let's add that in here. I'm doing this on purpose, by the way, cuz I'm going to send these as two separate prompts. This next one I'm gonna combine in like convert the application to use central package management because it's not totally related to this work, right? It's not needed, but I want to combine it in and we can see how it does. Like if we add in something extra like that, does it kind of just screw up and get confused? If it does, that's okay. We can get ourselves out of that. But I think for the most part, I think that's it. I think I probably spent more time on cores than I wanted to admit. So I think we're okay. So I think what I want to do is put a a bit of a a preamble on this first one. So I am building a feature in my website that needs two sets of work. The first will be for the front end and the second for the Azure function. Here is the first part. So I'm going to do it this way. So when I go to copy this into cursor then we can try that out. Then hopefully it knows like basically there's more coming. I am also curious if because I'm including in the second for the Azure function if it goes oh I need to make an Azure function. So we'll see. Let's try that out though. I am going to navigate a little bit back in time. So how far back do I got to go here? I got to go back to here. So let me go to reset current branch to here. Okay, now we're going to rock and roll in cursors. Who's nervous? I'm a little nervous. Okay, I'm going to see maybe there's one more thing I have. I actually don't in this solution. I I don't yet have like a a co-pilot instructions or anything I've written up for guidance. So, it's kind of going in blind, but that could be kind of fun, right? So let's go ahead and send this and see what happens. So I'll help you build the question submission feature for your code website. Let me start by exploring the current structure. This is pretty common. It's going to create the page and update the navigation. So so far so good because I wanted it to do UI changes in the beginning. I'm also hoping that once it's done and it hopefully doesn't go to do the Azure function that uh we can go run this and and check out the UI. So, that might be a good little pit stop along the way. Okay, so getting the navigation menu with a contact link with an icon. So, hopefully that works. Spoiler alert, when I had it make the UI for me the first time, I didn't tell it to put an icon, but it did put one. It's just that it wasn't rendering for some reason. So, whatever it decided to pick was not working. Now, the CSS for the chat dots icon. Okay, there's one more feature that I forgot to mention, but it's a minor one, and I'm not totally upset. I'm not going to go back and change this. I wanted the front page of my website to have a button that kind of like in the text that you're reading through like will jump you to the contact page like a hyperlink basically. I didn't ask it to do that. So, we're not going to have that feature. That's okay. A lot of work going on for this chat dots icon. It's far more time than I would hope to to see. What's going on cursor? So, I had to stop this because it was going on for too long and I am a little bit confused. So, nav menu razer.css. There's no content here. Um, it didn't do it and it just got stuck. So, I'm going to ask it again um and say you got I don't know how to tell the LLM that it didn't finish, but you got stuck trying to dots icon. Please continue. Oh no, I'm telling the LLM, please. I wonder if it's going to try to do it again and get stuck. Oh, it did it. I love when it does this kind of stuff. It's like, let me test it. Let me run this. Like, clearly did not didn't do it. And it's like, I'm done. Uh, okay. So, it thinks it's done, at least on the front end part. Let's go to Visual Studio. So, I'm going to run this out of Visual Studio. I'm going to start by building it because I don't think it's necessarily going to build. It completed. Okay, I was wrong. So, let's go ahead and run it. Okay, so it definitely added in the contact menu, but like you can see, um I think the size is a little weird. That's what's happening here. We can see if we can correct it. I'm not sure I care so much, but hey, like it made something, right? Submit anonymously. Cool. That collapses. I didn't tell it what platforms. So, when I made the original version of the site before recording this video, it picked I think similar things, maybe a different order. So, we got a username. Ask anything about software development, architecture, career advice, or any tech topic you'd like to hear about on Code Commute. Okay, so that's pretty interesting, right? Have a burning question about software element, submit it here, and it might be featured on Code Commute. Cool. Because again, you didn't get to see the original version when I was doing this, but I hinted at it earlier that it was basically kind of like a a tech support page is what it tried to generate. Like, you know, we're here to support you. We are going to answer your questions, but that's not it, right? Like, I am a YouTuber, so I wanted to reflect that. So, it did a pretty good job on this. Aside from this silly icon, which I'm not whatever. I don't really care cuz that's going to I could sit here and let it generate again, but I don't really care about that. Uh, zero words. Oh, the word counter doesn't work. This also was broken when I did it the first time. This one's counting words. And did I don't know if I actually said that. Maybe I did. Include I did say include a word counter. Oh. Um, that should have been character counter. Okay. I wanted a character count. And that way I could say like limit it to, you know, 5,000 characters or something. So, oh, what? It just started working. Why is it so delayed? So, I'm going to click out and back in and type. Okay, so there's that's definitely broken, but that's okay. I'm not going to chase this one down, I don't think. But so far the things if we had to go back into cursor to go have it correct things, we would want to say go update the icon, try to explain to it why it's broken. I would just say that the icon looks like it's being clipped. Maybe it's too large, it's distorted. That's how I corrected it the first time for myself. And on this one, what I would do is I would describe the behavior. So first of all, I would say change the word count to a character count and have it update as you are typing. And I would probably tell it that the current behavior is broken. So I would say the something along the lines of currently the word counter is only updating, you know, once the text box loses focus and it comes back, right? So that way it doesn't just change it to a character count from a word count and it still stays broken. That's probably how I would navigate that. But so far so good. Let's go see if we can get the other part in. And that means we need this part. And maybe I'll say now for the second part because earlier in the chat I was saying it's going to be two parts. So let's go see. Let me get that out of there too. I don't want that context. Okay. And submit. Let's see what happens. So it says I'll exp uh help you create Azure functions project and set up the email functionality. Let me start by exploring the current solution. So it seems to be a pretty common pattern, right? Let me go explore. It's getting templates to go install. That's not working. That's one of the things with cursor I find that is helpful is I mean it's going to sound kind of funny. I find that it's helpful that you can see it trying and then going, "Oh, that didn't work. Let me try something else." Instead of it being like, "Oh, that didn't work. I guess we're done here and we can't continue." This one's kind of interesting. So, you can install it on Windows. It actually did get stuck. And the funny part about this is I've already shown you The site's done and it didn't need this before. So, I don't want to install that. Create the new project with the correct Azure. I'll just see if it will do it. Ah, something I keep forgetting to remind cursor and other tools. Stop using .NET 8. Use the latest. Okay, so it's installing. It's getting packages. See, Mailkit was getting installed, right? So that will be helpful for us to send mail of course. It says adding the project into the solution. We can see the Azure function reference with the target framework of net 8. Although I do want nine but that's okay. It gave us some placeholder text. The way that it did this like this syntax should be like nested I guess which is kind of interesting. You know I didn't give it the details about how I wanted the configuration structured. I just said I want it to be loaded from environment variables. And I think it's doing Yeah, it's doing the central package management now, which is great. Disclaimer, I totally expect that our Azure Functions project is going to be broken because the first time it did it for me, it was broken. And this time it complained first, so I suspect it's not going to work. But let's see. We'll stop debugging. We'll get this thing loaded up already. Not a good sign. Okay, so SDK worker specify could not be found. So, we can't even get this loaded. Okay. So, I'm just going to tell Cursor because instead of just changing it myself, we're going to vibe code it, right? I'm going to tell Cursor that the project type's got to be changed to an SDK and the target framework will just get it to dot .NET 9 as well. So, let's go back to cursor and I'll just kind of write it out this way. So, change the SDK type of the Azure function project. We'll put that in there. So, it's just an SDK one. And then I will say version to 9.0. And now it has that. Hopefully we'll get that to load. We don't know if the rest of it's broken. So we'll see. And because I don't want to bore you with like trying to debug it and all of that, I'm going to walk through it with you. See what it looks like. Then we'll jump over to Azure and I can show you what I had to go change when things were up and running there. Seems like that's done. Let's go see if we can reload it now. And we can. We see class one in here. kind of funny. Give this a rename file. There we go. Okay. So, if we have a look here, instead of injecting a logger, it's injecting a logger factory. Kind of a weird pattern. I would not do that at all. Um, that's fine, though. I configuration is passed in, though. Let's go check. Oh, wait. There's no there's no entry point. So, this didn't make a program.cs file. I don't think that this is going to work at all to be honest. I was kind of expecting that this is going to be a problem. So, instead of trying to correct it because I feel like that's going to take quite some time and I'm looking at the clock, this is already 30 minutes into recording. I will probably walk you through the changes on the real one. But this is interesting. SMTP client doesn't have this, so it's just no async versions. I wonder why that's the case. Anyway, that's fine. Basically, the biggest problem here is that the way that I have this set up in sort of the real one is that you need to be able to have like the dependency injection and everything else set up. Unless there's something about Azure functions that I don't know and you can literally just declare it this way. I have not seen that work. So maybe someone watching this will say otherwise, but as far as I know, I need to go have like an Azure function builder go set up dependency injection, go build the functions, and then uh then they get defined this way, which is fine. But overall, like this does the right thing, right? I need to be able to get the request off of the body. It's going to deserialize it. It's checking for we didn't tell it what was mandatory, I guess. So, it's doing a little bit of validation. It needs to make sure the questions there. At least that's fine. And then it's going to set up SMTP to get this sent over through MailKit, which is great. So, it makes the message. Then there it is sending it. And there's the sort of JSON deserialization it's going to do. Overall, I think that's okay except for the fact that it's missing the entry point. So, let me go jump over to the real thing. And just to show you what I mean, I've kind of switched back to the main branch. You can see that there's a program.cs file here. So, you can see in this one, we have the actual builder being used, the function application create builder call here. I don't know if there was a different way to go do this, but this is how I've always made Azure functions using this pattern. And then I did call out to cursor that we needed to have environment variables set up for configuration. it didn't get a chance to do that cuz you're looking at the one that's off of my main branch right now. And then the rest of this is just setting up dependency injection, right? So this one ends up being a little bit lighter weight because we have a whole email service whereas the one that cursor made it kind of just jammed it all into one file. That's okay. But this is kind of what mine looks like now in order to deploy it because that's what I want to talk about next. So you can see that I did tell cursor that I want to manually deploy it. So how I do that is I just go over to here and then I say publish right you can see that it's here. So what I had to do before having this publish profile is I just went to new profile picked Azure and then walked through this. And the cool thing is once you've logged in if you have all your Azure accounts set up you can pick your subscription and just kind of walk through step by step. It gives you this publish profile which is up here and then you press the publish button and then again it just goes ahead and does it. I like doing this personally because as I said earlier, I'm not changing functions that often at all. I think that if I was building more complex applications that needed more Azure functions, I would probably just wire this up to continuous integration. It's just not something I'm familiar with yet. So, this is how I go about doing it. Now, if you hadn't already been in Azure to go make a functions app, that's totally fine. In order for that deployment step to work, what I needed to do is, of course, come into Azure. I already created my functions app, but you need to go make a new one. Kind of walk through the wizard for that. And then you can see like on mine, I have this deployed here. And that's super handy because once you have all this deployed, you can click into here if you need to go debug things. Like you can do a test run right from here. You can get the function URL. So you're going to want to do that once it's deployed. We can copy that, put it back into the submission form because it probably has a placeholder in there right now. If you need to be able to debug these things, then you can go over to the log stream in the left hand side here. It will connect in and then you can see what it's doing. So, if you're trying to troubleshoot it like I was doing, I was getting error messages coming back originally. Why was that happening? Well, the dependency injection was crashing on startup because I didn't have my environment variable set. So, I could use the log stream to go see that, which is super handy. I'm not going to wait for this to populate. I don't need to bore you on that. But the one other thing that was really important for me is that you see me scrolling all the way down here to this cores. I needed to make sure that because my Blazer site was trying to use the Azure function, it simply wasn't working. As a result, I needed to make sure that I had this added here and the www version as well. So by doing this, then automatically my Blazer site was able to start communicating with the Azure function. So that was sort of the cherry on top to be able to unlock it. So now if we go over to the live site code.com submit anonymously. This is from YouTube. This is the site that it made for me and we can see when I go to submit the question. Please work. There we go. Thank you. Your question has been submitted successfully. Make sure you're subscribed on YouTube. Friendly reminder, make sure to subscribe to the channel and you can check out Code Commute if you want to have software engineering questions answered or you want to see other people having their questions answered. So, thank you so much for watching. Cursor did an okay job on the second round. Still not perfect, but I think if we would have had the Azure templates loaded up, it probably could have done a better job. So, overall, it's growing on me. I don't hate using cursor so much, but it's still got a little bit of ways to go. So, I'll see you in the next video. Take care.

Frequently Asked Questions

What is Cursor and how does it help in building websites?

Cursor is an AI tool that I use to assist in coding features for my website. In this video, I demonstrate how to use Cursor to create an email submission form, which helps streamline the coding process by generating code based on my specifications.

What are the main features of the contact form I built using Cursor?

The contact form I built includes an option for users to submit their questions either anonymously or with their name and social media handle. It also features a question box and a word counter, although I realized I wanted it to be a character counter instead.

How do I deploy the Azure function created for the contact form?

To deploy the Azure function, I use Visual Studio to publish it directly to Azure. I create a publish profile, select my Azure subscription, and follow the steps to deploy. I also make sure to configure CORS settings in Azure to allow my Blazer site to communicate with the function.

These FAQs were generated by AI from the video transcript.
An error has occurred. This application may no longer respond until reloaded. Reload