[{"data":1,"prerenderedAt":439},["ShallowReactive",2],{"footer-primary":3,"footer-secondary":93,"footer-description":119,"100-apps-100-hours-ai-personalized-landing":121,"100-apps-100-hours-ai-personalized-landing-next":168,"sales-reps":187},{"items":4},[5,29,49,69],{"id":6,"title":7,"url":8,"page":8,"children":9},"522e608a-77b0-4333-820d-d4f44be2ade1","Solutions",null,[10,15,20,25],{"id":11,"title":12,"url":8,"page":13},"fcafe85a-a798-4710-9e7a-776fe413aae5","Headless CMS",{"permalink":14},"/solutions/headless-cms",{"id":16,"title":17,"url":8,"page":18},"79972923-93cf-4777-9e32-5c9b0315fc10","Backend-as-a-Service",{"permalink":19},"/solutions/backend-as-a-service",{"id":21,"title":22,"url":8,"page":23},"0fa8d0c1-7b64-4f6f-939d-d7fdb99fc407","Product Information",{"permalink":24},"/solutions/product-information-management",{"id":26,"title":27,"url":28,"page":8},"63946d54-6052-4780-8ff4-91f5a9931dcc","100+ Things to Build","https://directus.io/blog/100-tools-apps-and-platforms-you-can-build-with-directus",{"id":30,"title":31,"url":8,"page":8,"children":32},"8ab4f9b1-f3e2-44d6-919b-011d91fe072f","Resources",[33,37,41,45],{"id":34,"title":35,"url":36,"page":8},"f951fb84-8777-4b84-9e91-996fe9d25483","Documentation","https://docs.directus.io",{"id":38,"title":39,"url":40,"page":8},"366febc7-a538-4c08-a326-e6204957f1e3","Guides","https://docs.directus.io/guides/",{"id":42,"title":43,"url":44,"page":8},"aeb9128e-1c5f-417f-863c-2449416433cd","Community","https://directus.chat",{"id":46,"title":47,"url":48,"page":8},"da1c2ed8-0a77-49b0-a903-49c56cb07de5","Release Notes","https://github.com/directus/directus/releases",{"id":50,"title":51,"url":8,"page":8,"children":52},"d61fae8c-7502-494a-822f-19ecff3d0256","Support",[53,57,61,65],{"id":54,"title":55,"url":56,"page":8},"8c43c781-7ebd-475f-a931-747e293c0a88","Issue Tracker","https://github.com/directus/directus/issues",{"id":58,"title":59,"url":60,"page":8},"d77bb78e-cf7b-4e01-932a-514414ba49d3","Feature Requests","https://github.com/directus/directus/discussions?discussions_q=is:open+sort:top",{"id":62,"title":63,"url":64,"page":8},"4346be2b-2c53-476e-b53b-becacec626a6","Community Chat","https://discord.com/channels/725371605378924594/741317677397704757",{"id":66,"title":67,"url":68,"page":8},"26c115d2-49f7-4edc-935e-d37d427fb89d","Cloud Dashboard","https://directus.cloud",{"id":70,"title":71,"url":8,"page":8,"children":72},"49141403-4f20-44ac-8453-25ace1265812","Organization",[73,78,84,88],{"id":74,"title":75,"url":76,"page":77},"1f36ea92-8a5e-47c8-914c-9822a8b9538a","About","/about",{"permalink":76},{"id":79,"title":80,"url":81,"page":82},"b84bf525-5471-4b14-a93c-225f6c386005","Careers","#",{"permalink":83},"/careers",{"id":85,"title":86,"url":87,"page":8},"86aabc3a-433d-434b-9efa-ad1d34be0a34","Brand Assets","https://drive.google.com/drive/folders/1lBOTba4RaA5ikqOn8Ewo4RYzD0XcymG9?usp=sharing",{"id":89,"title":90,"url":8,"page":91},"8d2fa1e3-198e-4405-81e1-2ceb858bc237","Contact",{"permalink":92},"/contact",{"items":94},[95,101,107,113],{"id":96,"title":97,"url":8,"page":98,"children":100},"8a1b7bfa-429d-4ffc-a650-2a5fdcf356da","Cloud Policies",{"permalink":99},"/cloud-policies",[],{"id":102,"title":103,"url":81,"page":104,"children":106},"bea848ef-828f-4306-8017-6b00ec5d4a0c","License",{"permalink":105},"/bsl",[],{"id":108,"title":109,"url":81,"page":110,"children":112},"4e914f47-4bee-42b7-b445-3119ee4196ef","Terms",{"permalink":111},"/terms",[],{"id":114,"title":115,"url":81,"page":116,"children":118},"ea69eda6-d317-4981-8421-fcabb1826bfd","Privacy",{"permalink":117},"/privacy",[],{"description":120},"\u003Cp>A composable backend to build your Headless CMS, BaaS, and more.&nbsp;\u003C/p>",{"id":122,"slug":123,"vimeo_id":124,"description":125,"tile":126,"length":127,"resources":8,"people":8,"episode_number":128,"published":129,"title":130,"video_transcript_html":131,"video_transcript_text":132,"content":8,"status":133,"episode_people":134,"recommendations":149,"season":150,"seo":167},"bfb4b33c-1494-4111-8f33-d59bfde9df65","ai-personalized-landing","1059438000","Watch Bryant create a system that generates custom landing pages for target companies by scraping their websites and using AI to craft personalized sales pitches. With a mix of Directus hooks, FireCrawl for content scraping, and the Anthropic API for copywriting, he builds a complete workflow that transforms company data into engaging sales pages for his fictional developer seat cushion business.","8b694159-4108-4801-8254-3a42720143fe",61,9,"2025-03-10","Mission: AI Personalized Landing Page","\u003Cp>Speaker 0: Alright. Alright. Welcome back to, yet another episode of 100 apps, one hundred hours. I'm your host, Brian Gillespie. And in this episode, we're reaching back into the AI personalization bucket, and we're gonna build some personalized landing pages.\u003C/p>\u003Cp>If this is your first time on 100 apps one hundred hours, there are only two rules to the show. We have sixty minutes to plan and build an application, a clone of one of your favorite apps, or some totally random idea. No more, no less. And then number two is use whatever we have at our disposal. Could be past projects, could be AI, could be all sorts of crazy things that we might get into today.\u003C/p>\u003Cp>I've got no idea whether we're actually going to be able to, like, push this one across the finish line or not. So that should be exciting for this episode. Alright. So AI personalized landing pages. You know, there's another episode we've done in this season, like, content personalization.\u003C/p>\u003Cp>This time around, I wanna get very, very specific and say, hey, I have a target account or a a company that I wanna do business with. I wanna use AI to generate a landing page for them. So let's dive right in. We're gonna put sixty minutes on the clock, and let's go. Here we are.\u003C/p>\u003Cp>Alright. So I always like to start these by just discussing what are the features that we actually want out of this. Right? So as far as our functionality, we'll just make this freaking huge. Oh, not that big.\u003C/p>\u003Cp>Alright. So as far as the functionality we want out of this, here's how I'm thinking this is actually going to flow. We're going to add an organization to our back end, which is gonna be powered by Directus. And then a the AI is going to scrape the website. We want to use that content to generate and use content found to shift return.\u003C/p>\u003Cp>There we go. That's what I needed to generate a personalized landing page for that specific org. Okay? Display that using a front end. That's it.\u003C/p>\u003Cp>I would love to be able to do this on the fly, this part of it. Right? But, unfortunately, like, the LLM models are not super fast or well, if you use something like GROC, maybe. But the this step is gonna have to be done asynchronously. So we'll sort through that.\u003C/p>\u003Cp>Let's think through, like, our our actual data model now. So let's throw this up on the board. We're gonna have organization. And, honestly, like, I I could have a separate one for pages. You know, we've got, like, the page builder set up inside Directus, which is really nice.\u003C/p>\u003Cp>Something that we've showed in previous episodes where I can build a dynamic page based on predefined blocks. In this case, we might just keep it super simple. We've got an organization that I wanna target. Within that, we're gonna have a name. I need a website URL to scrape.\u003C/p>\u003Cp>And then the rest of it would be generated. Right? You know, let's call it blocks, I guess, generated blocks. Maybe we got a hero. I wanna have, like, a feature section.\u003C/p>\u003Cp>Call to action. Call to action, CTA. Man, I have outgrown my box here. We'll just add that up there. Alright.\u003C/p>\u003Cp>So this seems pretty solid, I guess. I what's our plan of attack? Right? What are we going to sell? What are we going to pitch?\u003C/p>\u003Cp>You know, what is our organization that we are setting up? Alright. So, as far as what I've got in the can already, I've got a Nuxt application. I've got a direct instance. So if we load up local host 3,000, I should see my Nuxt instance, my Nuxt application, just the same starter I use in all of these.\u003C/p>\u003Cp>And if I go to Logos eight zero five five, I should see a blank directus instance. That is not the one that I wanted to see. Let's control some of these Docker containers here, and then we'll fire this back up to see if we get what we want. Boop boop boop. Should be a blank instance.\u003C/p>\u003Cp>Great. Okay. Alright. So now I'm gonna log into this blank Directus instance. Directus is gonna give me all the back end functionality that I want and or need.\u003C/p>\u003Cp>And you could see it is totally blank. Right? So let's attack this from the back end perspective first, and then we'll switch to the front end, and then we'll switch to the back end, and we'll switch back and forth and back and forth until we all get confused with how many tabs I have open. Alright. Create a new collection.\u003C/p>\u003Cp>So let's create a new collection for our organizations. Right? As far as table names go, I prefer plural. Some people prefer singular. Totally up to you.\u003C/p>\u003Cp>We're just gonna add some of these specific default fields that Directus makes available to us. Like, hey. Is this published? Is there a sort order to this? Obviously, date created here will be populated with a timestamp of when this record gets created.\u003C/p>\u003Cp>Great. So now we have an organization. I'm gonna make this look very pretty. We will call it we'll search for maybe business. Forget I'm talking to myself here.\u003C/p>\u003Cp>I was about to ask you a question of which icon to use, but, still just talking to myself. Alright. So as far as our first field, right, we're going to add a the name of the organization. Pretty simple. Let's keep editing.\u003C/p>\u003Cp>I can make this shorter. We'll just go half width. So I am controlling the field, like the the actual form that we'll be interacting with as well as my data model and my APIs. So next, we will save this and let's add a website or URL. Let's just call it website.\u003C/p>\u003Cp>And what are we gonna do here? Let's go to advanced field creation. We could see that this is allowing a null value, but let's make sure that we set that to required. So when I fill out this form, it is going to make me input that. Now if I keep this as nullable, that means we could still potentially pass that value into the database as null, using the API.\u003C/p>\u003Cp>I could turn that off if I wanted to. I could also make sure this is unique as well, so that we don't generate this a million times. And for the display, we'll just show the raw value. Right? Is that it?\u003C/p>\u003Cp>Let's add a little icon just to make this a little fancy. This will be a link. Great. And now we have a website. And let's go ahead and make name required as well.\u003C/p>\u003Cp>We're gonna fill both of those things out. Boom. Amazing. I can go in. I can now add a name like Directus and a website, Directus.io.\u003C/p>\u003Cp>Save. Great. Notice that perfect little icon right there. It looks great. Right?\u003C/p>\u003Cp>I can even oh, no. I was gonna say I could point to it. I can point to it. There it is. Alright.\u003C/p>\u003Cp>So now we have this, like, data model. It's amazing. There's two fields here. This is really underwhelming as Bryant. Alright.\u003C/p>\u003Cp>So we've got an organization in our back end. Let's switch round to the front end, and let's start, like, fleshing something out. And this is where I will say, like, POC generation, AI has got an incredibly great for this, especially with, like, UI libraries like Shad CN and Tailwind for styling. It's gotten really good at creating components and things like that. So, what are we going to what are we gonna generate here?\u003C/p>\u003Cp>Like, what are we pitching? What are we what are we selling? Coffee mugs. Let's do something super developy developer ish. Maybe like a a seat cushion.\u003C/p>\u003Cp>Maybe we're gonna sell seat cushions. I'm hopefully, I look younger than I feel, but I've got three little girls. I've got a back that aches every day when I wake up. So maybe that's what we'll do here. We're gonna generate some seat cushions.\u003C/p>\u003Cp>Alright. So, when I think of the front end here, let's create a page. So let's create a new route for the org. Organization. I'm gonna wrap this in brackets there.\u003C/p>\u003Cp>Great. We'll do v base setup, script setup. Let's change that to length. Yes. And this is giant text, so that's a good thing.\u003C/p>\u003Cp>Alright. We got an organization. We're gonna fetch that organizational data. And behind the scenes, I've used this in so many videos. I'd never take the time to explain it.\u003C/p>\u003Cp>Basically, I'm using the Directus SDK. I've just got a quick little plug in as far as Nuxt goes. We're gonna pull the direct as URL from the configuration. We're gonna create a really simple direct as client, and we're gonna provide that to the Nuxt application. So the first time this application spins up or, you know, when it loads, it creates that instance for us and makes it globally available through something like this where we could say, Directus use Nuxt app.\u003C/p>\u003Cp>The other thing that I'm gonna do here, I'm gonna import read items from the Directus SDK and then we're gonna fetch this data. So we'll say data, that's gonna be organization. No thank you AI. Wait. We're gonna use the async data composable from Nuxt, just a handy little helper for caching.\u003C/p>\u003Cp>We're gonna call this organization organization. We're gonna get that organization from our routes, route.params.organization. No. We don't want that. We're going to do it this way, route.params.organization.\u003C/p>\u003Cp>We're gonna do direct us dot request. Yes. Direct us request. Read items, and we're just gonna wrap that. And do I have some nice formatting?\u003C/p>\u003Cp>Great. We got some formatting. Okay. So what are we doing here? We're looking for a slug.\u003C/p>\u003Cp>We don't really have a slug set up yet. So let's just do an ID. And maybe we do wanna set up a slug, maybe we don't. Route dot params ID. You'll notice this filter syntax here.\u003C/p>\u003Cp>Directus has a ton of different filter rules that I can use to create deeply nested or crazy queries where I can fetch everything I need in a single API call. And then I'm just gonna go in and log this out on the page. Is this possible? Let's go into Directus and just make this process easy for me as well. There is a button links option here which is just presentational.\u003C/p>\u003Cp>And we're gonna say view on website. Give it a label, arrow up link. Do it is there like an external link? Arrow. Let's just go arrow caret ray.\u003C/p>\u003Cp>Okay. And we're gonna say HTTP, we want the URL local host 3,000 is what we're running on. And then we're gonna run this at the ID. Great. Well, it's safe.\u003C/p>\u003Cp>Now I should get a button on this page where I can view on the website. And lo and behold, it looks amazing. This is the most beautiful page ever. We're just gonna go back in and edit our permissions. So by default, Directus keeps everything secure, keeps a tight lid on everything.\u003C/p>\u003Cp>So this public policy that we have doesn't have any access to our data. So let's go in and add read access for organizations and let's let's set files as well in case we decide to upload some pictures of our amazing seat cushions that we're going to sell. And now if I refresh the page, we could see, great, I have a name, I have a website. Alright. That's kinda underwhelming.\u003C/p>\u003Cp>Not great. So let's have it design. Let's retray, here. We are going to create I'm gonna use Claude's sonnet, and let's create a landing page. You are let's let's back up a minute.\u003C/p>\u003Cp>What do we want our landing page to look like actually? Right? So we probably got like a hero. We've got a features for our seat cushions, seat cushions, hero section. And then we've got like a like a buy button.\u003C/p>\u003Cp>Buy button. Buy now. CTA. Alright. So that's gonna be the structure for our page.\u003C/p>\u003Cp>Here we go. We are going to flesh this out. You know, we probably want to you are are we gonna, like, one shot this? Let's see. Well, if I do this, you are a expert I I don't think you really need to do this because it's picking up up whatever I have, but create a hero section component for a online store that sells seat cushions to developers.\u003C/p>\u003Cp>A beautiful, well designed view three component using alright. So one of the features I've been experimenting with in cursor is this documentation feature. This starter has like the Nuxt UI library built into it. Which version am I actually running? Did I upgrade this to the latest one?\u003C/p>\u003Cp>Yeah. I'm running the alpha version. So we're gonna use those docs and tell when CSS. We'll see what we come up with here. Let's create a beautiful new component.\u003C/p>\u003Cp>You page hero. I don't know I don't know that I have any of these actually. Just you don't use our Nuxt UI components after all. Okay. So we can see what is coming up with hero section.\u003C/p>\u003Cp>We got a feature, ergonomic design. Yeah. I'm kinda curious to see what it comes up with as far as, like, the data model around this as well. We'll just go ahead and flush this out for it here while component section, features. Oh, this is running kinda slow.\u003C/p>\u003Cp>New collection, blah blah blah, right column. Yeah. It would probably even be easier just to go into, like, Tailwind UI and find some of these components here. They've got some nice ecommerce components. Let's look at it like a hero section.\u003C/p>\u003Cp>Alright. Let's just we'll just see what it came up with first and accept this. We'll go back to our organization. We'll insert this component in here. This is our hero section.\u003C/p>\u003Cp>Great. Cushion. JPEG. Is there a cushion dot JPEG? Hero section.\u003C/p>\u003Cp>Where is this cushion dot jpeg cushion hero dot jpeg. Alright. Let's bring in one of our first AI big guns here. We'll go to replicate, and I'm just gonna use our flux model here. It will create a product image of a futuristic seat cushion for developers if I could actually spell, that'd be dangerous.\u003C/p>\u003Cp>Developer's seat cushion, developer's desk chair. I don't think punctuation is hugely important here. Let's see what we come up with. For 6¢ an image. What are we gonna get out of this?\u003C/p>\u003Cp>That looks pretty pretty wicked awesome there. Right? So we're gonna download that. Let's dump this into our assets folder, and we'll call it seat cushion dot JPEG, and we'll just update that here. Alright.\u003C/p>\u003Cp>So this should be assets, images slash seat cushion. And oh, what have we got here? Something weird is going on. Better comfort for better code. There we go.\u003C/p>\u003Cp>Alright. Now we're getting somewhere, except this looks really odd with our price badge. Something's going on there. Let's just comment that out. There we go.\u003C/p>\u003Cp>We got our seat cushion. This is great. Alright. Now let's have it designed something else. Right?\u003C/p>\u003Cp>Let me just shrink this down just a little bit. Feature alright. So we want this to be our headline. Right? So let's flush this out a little bit more.\u003C/p>\u003Cp>This is gonna be our headline. This will be our description. I'm just trying to think through like our what our props are gonna look like for this. Define props, features as a feature. Great.\u003C/p>\u003Cp>Learn more, shop now. Better comfort for better code. This is a new collection. Badge. Alright.\u003C/p>\u003Cp>So we'll just stick that in our props. Now we got badge, got features. Do we actually want the icons we can. I think I've got the Nux icon library built into this so we could simplify this, like hero icons. There we go.\u003C/p>\u003Cp>I don't know what other hero cons we have here. Shopping bag, check circle. There we go. And then we'll, like, flesh this out. Where is that icon at?\u003C/p>\u003Cp>Icon. Feature dot icon. Yeah. So we could ditch all of this and make this a little bit cleaner. We'll keep that.\u003C/p>\u003Cp>Right? You icon. Name equals feature dot icon. We'll just ditch this, ditch that, clean this up a bit, and we should still have our icons. Great.\u003C/p>\u003Cp>And then we're gonna move out features out of here, we'll put that into this. So for now, we'll just say here's our data, our data. We'll drop our features here. Sometimes it is frustrating as I'll get out to properly just navigate using these AI tools. The tab tab tab is it's nice when it works well.\u003C/p>\u003Cp>When you have all these extensions included, it does get a little bit messy. Let's check on time. Where is Figma? Thirty seven minutes. Alright.\u003C/p>\u003Cp>Better get to it, g. Alright. If I hit refresh, are we actually going to let's call this data, and then we'll go back into our hero section. We'll just wrap all this up into data. There we go.\u003C/p>\u003Cp>There we go. Data dot badge, data dot headline, shop now, learn more, data dot features. Okay. So maybe that is a little long as far as a headline. What do we have previously?\u003C/p>\u003Cp>Yeah. Alright. Comfort for better code. There we go. Okay.\u003C/p>\u003Cp>Now, this is our data. Right? This is our data structure. Maybe we tell this to generate. Alright.\u003C/p>\u003Cp>So how are we gonna generate the actual code here? Like, how are we gonna generate the personalization of this specific page? Let's just ditch the code part. There's our website. Looks great.\u003C/p>\u003Cp>How are we gonna personalize this? So for that, let's kick off a Directus extension, basically. Basically. Yeah. Nothing basic about it.\u003C/p>\u003Cp>So what I'm thinking we'll do here, we'll set up a custom Directus extension so that whenever I am adding a new organization, it will create that data for us. So let's also do this where we'll go in and we'll call this just page data. Page data. Page content. It doesn't really matter what we call it.\u003C/p>\u003Cp>I'm just gonna set it to be JSON. That's what we're gonna ask back from the API. Alright. Let's kick off this extension. So I'm inside my Directus directory.\u003C/p>\u003Cp>We're probably gonna go into CD extensions within that. And then I'm gonna go n p x create direct us or create dash direct us dash extension latest. And I am going to create a let's do a custom hook. This is generate personalized page, custom landing page, AI landing page. We use TypeScripts.\u003C/p>\u003Cp>We'll go ahead and install the dependencies. And one of the things that I've got set up here inside my Docker Compose for this, obviously, like, I'm I'm I'm creating a volume for the extensions here so we could pull those in. But I'm also somewhere in here. I have extensions auto reload set so that whenever we build this extension, Directus is going to look for that and reload this extension or at least it should. So we'll go into CD AI landing page, npm dev.\u003C/p>\u003Cp>Alright. So let's actually open this bad boy up and see what we've got here. Items dot create. Okay. So now I'm just quickly going to cheat a bit and pull up the direct to stocks.\u003C/p>\u003Cp>Hooks, custom API hooks. So what we're looking for here is after this item is created, and I think the structure for a collection itself is a collection name dot items dot create. This is what we're gonna do. So our filter will look something like the or our action here will look something like this. We don't necessarily need this.\u003C/p>\u003Cp>Alright. So we're gonna say organizations dot items dot create, organization created, and this will be async. And what this is going to receive should be alright. We're gonna get the context here. We can see what that context is gonna look like.\u003C/p>\u003Cp>That's how we're gonna initiate some services. What does the action receive? Right? The action receives the event name and a callback function that is executed whenever the thing is submitted. Alright.\u003C/p>\u003Cp>Extensions guys. Do we have one on hooks? Use hooks to validate phone numbers. Items that create input collection. So we're gonna get the payload, I'm assuming, and the content, item context.\u003C/p>\u003Cp>Let's see just kinda what we get here. Extension's changed. Okay. Test httpstest.co. If I check my Docker logs, I cannot import.\u003C/p>\u003Cp>Let's just stop and spin up the Docker container one more time. Make sure we're actually getting that. Okay. I could see that extension being initialized. Oh my gosh.\u003C/p>\u003Cp>That gets ugly, doesn't it? Alright. Let's try this one more time. We'll delete testco, test Co. Are we seeing any console log?\u003C/p>\u003Cp>I'm not seeing any logs here. Async, define hook. Extensions reloaded. Organization oh, duh. You gotta use the right right syntax, Brian.\u003C/p>\u003Cp>Frustrating to be under the clock. Testtest.co. Hit save. Okay. So now we're seeing some stuff here.\u003C/p>\u003Cp>Great. Alright. There's our holy moly. Alright. So that is our there's the context that we're getting there.\u003C/p>\u003Cp>Organization created. There's the payload that we're receiving. And then we're getting the item context. Okay. Great.\u003C/p>\u003Cp>Alright. So what we're gonna do, what do we want to actually happen when this is going to pop off? There's a third party tool that we're gonna use for this called FireCrawl that I've been testing. Right? So let's try this.\u003C/p>\u003Cp>We're going to add Firecrawl. Js. Alright. So we're gonna go to our extension that we're running. I'm gonna install this library from FireCrawl.\u003C/p>\u003Cp>And we're gonna go ahead and one of the other things that I'm gonna do, we're gonna call this the organization's service. We're going to extract that out of the context. Const request. No. It's gonna be the services out of the context, then the item service through the services.\u003C/p>\u003Cp>And we're gonna call new item service. Great. And this is gonna give us the ability to update. Right? So we're gonna initialize that service.\u003C/p>\u003Cp>We've got that installed. Now let's copy our code here. I'm hoping this is my live API. New FireCrawl app. We need to import that.\u003C/p>\u003Cp>Scrape a single web page. Got it. We'll move that down below our item service, and we're gonna get the scrape result. And for now, let's just oh, I can already see the typo happening here. That's gonna be frustrating for me.\u003C/p>\u003Cp>And we're gonna say await updated org equals await organizationservice.update.one. Data, does that need to be wrapped in data? I don't know. Scrape content. Alright.\u003C/p>\u003Cp>We're gonna return the updated org, and let's wrap this in a try catch as well. Try catch. Console dot error. See if we get some formatting. Nice.\u003C/p>\u003Cp>Okay. Let's fire up the dev server for this and cross our fingers. Right? The other thing I need to update here, we're gonna have to go in and figure out which tab has all of my browsers in it. Maybe we just move that to a single browser for now.\u003C/p>\u003Cp>And we're gonna add a new field for this. We're gonna call it, scraped result. Scraped result. I don't know what this is gonna be. I'm assuming scraped content.\u003C/p>\u003Cp>I'm assuming this is gonna be JSON data that we're gonna get back. I guess I could look and see. Success data. You know, we could also just store the markdown. That might be easier.\u003C/p>\u003Cp>Where do we go? Scrape content. Let's delete that. Where does this store the markdown? Scraped.\u003C/p>\u003Cp>Scraped content. Alright. So according to FireCrawl, if we do this correctly, we're gonna get something like this. So with the scrape result dot data dot markdown. Fingers crossed.\u003C/p>\u003Cp>That's what we're gonna get. We could also just console log that to verify scrape content, scrape result. Alright. Let's go for it and see one last thing that I wanna do here. This is not, using, like, any of our accountability, so do not do this in production.\u003C/p>\u003Cp>But we'll just allow the public to create and update all the content on the underlying instance. Great. Love how secure I am being. I'm sure everybody on my team would be thrilled. Alright.\u003C/p>\u003Cp>So let's just go to Directus as the example. HTTPS, Directus.io. That's our website. Oh, I've already got directis.io hard coded in there as well, so we're probably gonna want to pick that up out of the payload as well. Can we still see that payload?\u003C/p>\u003Cp>No. Let's do this. We'll see the payload.website URL. We'll see if this actually works. Fingers crossed that it does.\u003C/p>\u003Cp>Scrape content. Save. What happens on this side of it? Around URL must be a top level domain or valid path. So I'm getting that error there.\u003C/p>\u003Cp>It's fine. Should set this up on update or create. Directus.io. Save and stay. Do we see what we get back?\u003C/p>\u003Cp>Is this thing still running in the background? What are we doing here? I got no visibility into what's happening here. Let's try it again. Directus.\u003C/p>\u003Cp>Directus. Io. Hit save. Must be a failed to scrape URL. URL must oh, duh, dummy.\u003C/p>\u003Cp>This is where it helps to define types so you don't make these same silly mistakes as I have. So I've called this field website. I was calling it website URL here, so not actually passing any website. Cannot read properties of collections. So there's our scrape results.\u003C/p>\u003Cp>Do we see the markdown? There's our markdown. Cannot update one. What am I doing wrong here? We're not updating the schema.\u003C/p>\u003Cp>We need to extension service, access items. Yes. Here we go. This is what I actually need to see. Alright.\u003C/p>\u003Cp>So we got our context. We're gonna do services get schema. We need that schema. And we're also gonna need the accountability schema. So in our item service definition, we don't wanna do this.\u003C/p>\u003Cp>We're gonna do this. Equals await. No AI. No. We're gonna await git schema.\u003C/p>\u003Cp>So we're gonna get the schema from our context and on the accountability side, accountability. That'll be accountability. If we just destructure that, I think that gives us what we need. Let's go back and try it again. Love hacking this stuff together on the fly.\u003C/p>\u003Cp>No pressure. Directus directus dot I o. Hit save and stay. Let's just watch over here and see what happens. Fire crawl seems to take a little bit, so that is forbidden.\u003C/p>\u003Cp>I don't know what we're getting over here. Can I just leave off the accountability object? How many times am I gonna create this before I just do update? Directus Directus dot I o. Save.\u003C/p>\u003Cp>Probably burning through these fire crawl credits as we speak as well. That that that that that, forbidden. You don't have permission to access this. Why is that not the case? What is the alright.\u003C/p>\u003Cp>So let's stop loading that. Let's just say console dot log the payload. Actually, I think it's I goofed up, didn't I? What are we gonna be receiving here? It's not gonna be it'll be payload dot key.\u003C/p>\u003Cp>Payload dot let's just log the whole payload again and see. Just comment out this. Comment out. Directus Directus dot I o slash payload key. Okay.\u003C/p>\u003Cp>Duh. You're smarter than that, Brian. Alright. So we need this key. That's what we're getting is the key payload dot key.\u003C/p>\u003Cp>So here, payload dot key. There's the event. There's the key. There's the organization of the collection we already got. Alright.\u003C/p>\u003Cp>Let's keep rolling and maybe try to actually complete this one. Directus. Directus dot I o. Save. Can we actually get the scrape content?\u003C/p>\u003Cp>Can we actually complete this on time? Can we do any of these things in any sort of actual working fashion? Is this actually gonna work? Will we know? How do I know?\u003C/p>\u003Cp>Console.logupdatedorg. Directus. Directus I o. Save. There's the payload.\u003C/p>\u003Cp>Fire crawl really takes a bit. Status code, 200. Updated org. Is this actually gonna see what we want? No.\u003C/p>\u003Cp>Of course not. It's not gonna update the right one. Data dot scraped content. I'm sure this is what we need to do here. Right?\u003C/p>\u003Cp>Update one. Let's look at the services. Update an item. Yep. It's not inside data.\u003C/p>\u003Cp>So I don't need that to wrap. Gosh. I'm just eating up all the time. I wish I spent more time with hook extensions. Super powerful because you're basically just updating the underlying Express app instance anyway.\u003C/p>\u003Cp>But alright. So now let's reach for anthropic. If we hit refresh, do we ah, still not getting the data that I want. Right? It's saying that it's updated that org.\u003C/p>\u003Cp>Scrape result. Scrape result scrape content. So they tricked me. It's not it's not as it shows. It's actually not there's actually no data attribute there.\u003C/p>\u003Cp>It's basically just scrape result dot markdown. Alright. Last freaking time for the scraped content, Directus Directus dot I o. I was not planning on doing this much troubleshooting. Behind the scenes here, I'm gonna go in and just create a API key for anthropic.\u003C/p>\u003Cp>Hundred apps. There's my API key. Updated org. Did we actually get what we want? Holy moly.\u003C/p>\u003Cp>We got some scraped content in here. Okay. Alright. So now the next step in the puzzle is going to be call the Anthropic API to generate a landing page for the organization with the JSON schema, page data. Alright.\u003C/p>\u003Cp>So now this is one of the things where I've been leaning on the Vercel API, or AI SDK. So I'm just gonna install it here, p m p I. This is just AI. And they've got a way. The last time I checked, the Anthropic does really well.\u003C/p>\u003Cp>Like, SONNET does really well at copywriting. But it doesn't have the JSON mode that the ones like OpenAI have. So I'm just gonna go in and look for provider management providers. Where are my providers? Providers and models.\u003C/p>\u003Cp>Looks for the anthropic provider. I'm gonna add it as well. And let's see what we can get here. Import anthropic. So I'm gonna import this guy.\u003C/p>\u003Cp>And then we're also going to do what? Create anthropic. We'll do that here. Now what I would normally do is this context object should have an e and v variables as well. API key.\u003C/p>\u003Cp>I'm not gonna do that here because I am worthless, basically. No. We're eating up a lot of time. Base URL, API key, generate text. We want to generate objects.\u003C/p>\u003Cp>So there's our anthropic client that we're creating. Don't mind that API key. Now let's define what do we need? We need Zod as well, p m Zod. And we're going to use was it generate object in here?\u003C/p>\u003Cp>See if we can find it. Generate object. Alright. Generate object from AI. Okay?\u003C/p>\u003Cp>Now what we're trying to do is just basically, we're gonna define a Zod schema of the object that we want, and that's gonna be our hero section. Right? Zod schema. We're gonna lean on the props. There we go.\u003C/p>\u003Cp>Okay. So now I'm just gonna copy this wholesale. We're gonna stick this in our custom hook. Again, not being careful at all about separation of concerns or cleanup. So there's our Zod schema.\u003C/p>\u003Cp>We want the object to return hero section schema. Alright. So now let's look up what we actually want this to how we're gonna work this. Generate object. We don't want testing.\u003C/p>\u003Cp>There's gotta be a better during text, during structured data. Alright. So our model okay. So we want the object equals await generate object. I'm hoping this is right.\u003C/p>\u003Cp>Fingers crossed with AI. Generate a landing page for the following organization with the content. Okay. For the organization payload. Name, the following content.\u003C/p>\u003Cp>You are an expert copywriter, and your job is to generate amazing landing pages that are personalized for our target clients. We sell the best desk chair cushions in the world for developers. Schema. There's our schema. That's our Zod model.\u003C/p>\u003Cp>Okay. When we get that back, what are we gonna do with the object? We are going to update the org, updated org two. It's fancy, fancy, fancy. Okay.\u003C/p>\u003Cp>Alright. How we doing on time? We got nine minutes to try and figure this out. Let's just PM, PM, dev this bad boy up and see if this is actually gonna come out at all. We're rebuilding this extension.\u003C/p>\u003Cp>Dun dun dun dun dun. I'm gonna nuke this entirely. Let's try it again. Let's see if it works for directus.io. We hit save.\u003C/p>\u003Cp>I could check the logs on Docker. Create anthropic is not defined. Anthropic. Response. Anthropic.\u003C/p>\u003Cp>Where is that? Providers and models. Anthropic provider. Create anthropic. Import the default provider.\u003C/p>\u003Cp>Oh, no. We could just import the what am I doing? Create create anthropic. Organizations. Oh, no.\u003C/p>\u003Cp>Directus. Duh. Directus .I o. Hit save. There's the payload.\u003C/p>\u003Cp>Obviously, it would be great to have visibility into this. And one tool that I've been using as of late is ingest. Great tool for something like this, generated hero section. This is gonna be nice, doc. Okay.\u003C/p>\u003Cp>Alright. So now before we reveal what it generated, let's just try to make sure this is actually gonna work. So instead of the data here, we're just gonna use the organization dot data dot page data. Organization dot page data. Generated hero section.\u003C/p>\u003Cp>That looks nice. Organization dot page data. Dun dun dun, the big reveal. Close that guy out. No.\u003C/p>\u003Cp>Status message. What is the status message? Did we actually get the page data generated? Okay. We got the page data generated.\u003C/p>\u003Cp>It looks like it's coming back with data here as well. So we should probably fix that in our hook. Page data page data is what? Object dot data. But for now, what I'm gonna do, I'm gonna just strip this out.\u003C/p>\u003Cp>Right? Great. And we refresh. We refresh. We refresh.\u003C/p>\u003Cp>No. What is going on? Organization. I'm excited for this, and I'm hoping we could get this to work. Right?\u003C/p>\u003Cp>Why am I not getting any of my data? Organizations. Access policies. We can see that organize oh, that's because it's not the right organization. Alright.\u003C/p>\u003Cp>I was using the old organization. We blew that one away like a hundred times. Right? This is probably where you'd wanna slug. Five minutes left.\u003C/p>\u003Cp>What do we have on the clock, Johnny? No. It's not working. Boy. Alright.\u003C/p>\u003Cp>There's our page data, organization dot page data. There's the scrape content. Why are we not seeing that? Right? Organization.\u003C/p>\u003Cp>Let's try it now. Status code. What is the error that we're receiving? V if organization dot page data. I could see the page data, man.\u003C/p>\u003Cp>Organization. Oh, duh. Gosh, man. What an idiot. Alright.\u003C/p>\u003Cp>So I I've done this on another episode as well. We're gonna transform this to get data. Where is this at? Is it here? Transform data.\u003C/p>\u003Cp>I don't know if this is how it functions. Error results, organization. I'm not sure the exact syntax, and I'm not gonna mess around with it. So we're gonna do this. It's gonna be organization.\u003C/p>\u003Cp>Boom. Bam. Directus plus Comfy Desk revolutionize your development experience, Seamless integration. Integrate Directus' flexible back end with your favorite front end while sitting comfortably on comfy desk cushions. Tailor your with adjustable cushions.\u003C/p>\u003Cp>Perfect. Alright. So now we have landing pages that are personalized for a specific client within, like an AI workflow. Right? So let's try this with some other company.\u003C/p>\u003Cp>Let's say OpenAI. I guess just to to pit these guys against each other here is this OpenAI.com. OpenAI Com. We'll hit save. And hopefully, this all runs, works nicely on the back end.\u003C/p>\u003Cp>There's the scrape result. You know, if I wanted to get really fancy, obviously, I could take this to the extreme here. But let's look at OpenAI. We'll view this on the website. What is going on?\u003C/p>\u003Cp>For noose proper next string, OpenAI. Okay. This one is not super strong. Right? Not sure what the scrape data result was.\u003C/p>\u003Cp>It looks like Firecrawl didn't do a great job with their website. Right? Let's try Apple.apple.com. Save. And we'll see what it comes back with.\u003C/p>\u003Cp>There's the scrape content. And, again, this is just coming back with markdown. You know, I might have better luck with, like, actual JavaScript parsing or something like that. But boom. Elevate your comfort coding experience with Apple inspired comfort, the iCushion Pro.\u003C/p>\u003Cp>Anyway, that's it for this episode. We've achieved this. I'm pushing a stop button on it. One minute left, we have basically fleshed out this personalized landing page where we add an organization, we use AI to scrape it, we then we generate content using LLMs, based on a specific schema, and then boom, we've got a personalized landing page that we could share with them. As far as next steps for me would probably be, like, setting this up on, like, a pretty URL or a slug, you know, adding this to some type of outbound, like, outreach campaign potentially.\u003C/p>\u003Cp>That's it though. It's amazing what you can put together in just an hour with tools like Cursor, Directus, Nuxt, Anthropic, all these different things come together to create stuff that's fun to build. I'll catch you on the next episode. Peace.\u003C/p>","Alright. Alright. Welcome back to, yet another episode of 100 apps, one hundred hours. I'm your host, Brian Gillespie. And in this episode, we're reaching back into the AI personalization bucket, and we're gonna build some personalized landing pages. If this is your first time on 100 apps one hundred hours, there are only two rules to the show. We have sixty minutes to plan and build an application, a clone of one of your favorite apps, or some totally random idea. No more, no less. And then number two is use whatever we have at our disposal. Could be past projects, could be AI, could be all sorts of crazy things that we might get into today. I've got no idea whether we're actually going to be able to, like, push this one across the finish line or not. So that should be exciting for this episode. Alright. So AI personalized landing pages. You know, there's another episode we've done in this season, like, content personalization. This time around, I wanna get very, very specific and say, hey, I have a target account or a a company that I wanna do business with. I wanna use AI to generate a landing page for them. So let's dive right in. We're gonna put sixty minutes on the clock, and let's go. Here we are. Alright. So I always like to start these by just discussing what are the features that we actually want out of this. Right? So as far as our functionality, we'll just make this freaking huge. Oh, not that big. Alright. So as far as the functionality we want out of this, here's how I'm thinking this is actually going to flow. We're going to add an organization to our back end, which is gonna be powered by Directus. And then a the AI is going to scrape the website. We want to use that content to generate and use content found to shift return. There we go. That's what I needed to generate a personalized landing page for that specific org. Okay? Display that using a front end. That's it. I would love to be able to do this on the fly, this part of it. Right? But, unfortunately, like, the LLM models are not super fast or well, if you use something like GROC, maybe. But the this step is gonna have to be done asynchronously. So we'll sort through that. Let's think through, like, our our actual data model now. So let's throw this up on the board. We're gonna have organization. And, honestly, like, I I could have a separate one for pages. You know, we've got, like, the page builder set up inside Directus, which is really nice. Something that we've showed in previous episodes where I can build a dynamic page based on predefined blocks. In this case, we might just keep it super simple. We've got an organization that I wanna target. Within that, we're gonna have a name. I need a website URL to scrape. And then the rest of it would be generated. Right? You know, let's call it blocks, I guess, generated blocks. Maybe we got a hero. I wanna have, like, a feature section. Call to action. Call to action, CTA. Man, I have outgrown my box here. We'll just add that up there. Alright. So this seems pretty solid, I guess. I what's our plan of attack? Right? What are we going to sell? What are we going to pitch? You know, what is our organization that we are setting up? Alright. So, as far as what I've got in the can already, I've got a Nuxt application. I've got a direct instance. So if we load up local host 3,000, I should see my Nuxt instance, my Nuxt application, just the same starter I use in all of these. And if I go to Logos eight zero five five, I should see a blank directus instance. That is not the one that I wanted to see. Let's control some of these Docker containers here, and then we'll fire this back up to see if we get what we want. Boop boop boop. Should be a blank instance. Great. Okay. Alright. So now I'm gonna log into this blank Directus instance. Directus is gonna give me all the back end functionality that I want and or need. And you could see it is totally blank. Right? So let's attack this from the back end perspective first, and then we'll switch to the front end, and then we'll switch to the back end, and we'll switch back and forth and back and forth until we all get confused with how many tabs I have open. Alright. Create a new collection. So let's create a new collection for our organizations. Right? As far as table names go, I prefer plural. Some people prefer singular. Totally up to you. We're just gonna add some of these specific default fields that Directus makes available to us. Like, hey. Is this published? Is there a sort order to this? Obviously, date created here will be populated with a timestamp of when this record gets created. Great. So now we have an organization. I'm gonna make this look very pretty. We will call it we'll search for maybe business. Forget I'm talking to myself here. I was about to ask you a question of which icon to use, but, still just talking to myself. Alright. So as far as our first field, right, we're going to add a the name of the organization. Pretty simple. Let's keep editing. I can make this shorter. We'll just go half width. So I am controlling the field, like the the actual form that we'll be interacting with as well as my data model and my APIs. So next, we will save this and let's add a website or URL. Let's just call it website. And what are we gonna do here? Let's go to advanced field creation. We could see that this is allowing a null value, but let's make sure that we set that to required. So when I fill out this form, it is going to make me input that. Now if I keep this as nullable, that means we could still potentially pass that value into the database as null, using the API. I could turn that off if I wanted to. I could also make sure this is unique as well, so that we don't generate this a million times. And for the display, we'll just show the raw value. Right? Is that it? Let's add a little icon just to make this a little fancy. This will be a link. Great. And now we have a website. And let's go ahead and make name required as well. We're gonna fill both of those things out. Boom. Amazing. I can go in. I can now add a name like Directus and a website, Directus.io. Save. Great. Notice that perfect little icon right there. It looks great. Right? I can even oh, no. I was gonna say I could point to it. I can point to it. There it is. Alright. So now we have this, like, data model. It's amazing. There's two fields here. This is really underwhelming as Bryant. Alright. So we've got an organization in our back end. Let's switch round to the front end, and let's start, like, fleshing something out. And this is where I will say, like, POC generation, AI has got an incredibly great for this, especially with, like, UI libraries like Shad CN and Tailwind for styling. It's gotten really good at creating components and things like that. So, what are we going to what are we gonna generate here? Like, what are we pitching? What are we what are we selling? Coffee mugs. Let's do something super developy developer ish. Maybe like a a seat cushion. Maybe we're gonna sell seat cushions. I'm hopefully, I look younger than I feel, but I've got three little girls. I've got a back that aches every day when I wake up. So maybe that's what we'll do here. We're gonna generate some seat cushions. Alright. So, when I think of the front end here, let's create a page. So let's create a new route for the org. Organization. I'm gonna wrap this in brackets there. Great. We'll do v base setup, script setup. Let's change that to length. Yes. And this is giant text, so that's a good thing. Alright. We got an organization. We're gonna fetch that organizational data. And behind the scenes, I've used this in so many videos. I'd never take the time to explain it. Basically, I'm using the Directus SDK. I've just got a quick little plug in as far as Nuxt goes. We're gonna pull the direct as URL from the configuration. We're gonna create a really simple direct as client, and we're gonna provide that to the Nuxt application. So the first time this application spins up or, you know, when it loads, it creates that instance for us and makes it globally available through something like this where we could say, Directus use Nuxt app. The other thing that I'm gonna do here, I'm gonna import read items from the Directus SDK and then we're gonna fetch this data. So we'll say data, that's gonna be organization. No thank you AI. Wait. We're gonna use the async data composable from Nuxt, just a handy little helper for caching. We're gonna call this organization organization. We're gonna get that organization from our routes, route.params.organization. No. We don't want that. We're going to do it this way, route.params.organization. We're gonna do direct us dot request. Yes. Direct us request. Read items, and we're just gonna wrap that. And do I have some nice formatting? Great. We got some formatting. Okay. So what are we doing here? We're looking for a slug. We don't really have a slug set up yet. So let's just do an ID. And maybe we do wanna set up a slug, maybe we don't. Route dot params ID. You'll notice this filter syntax here. Directus has a ton of different filter rules that I can use to create deeply nested or crazy queries where I can fetch everything I need in a single API call. And then I'm just gonna go in and log this out on the page. Is this possible? Let's go into Directus and just make this process easy for me as well. There is a button links option here which is just presentational. And we're gonna say view on website. Give it a label, arrow up link. Do it is there like an external link? Arrow. Let's just go arrow caret ray. Okay. And we're gonna say HTTP, we want the URL local host 3,000 is what we're running on. And then we're gonna run this at the ID. Great. Well, it's safe. Now I should get a button on this page where I can view on the website. And lo and behold, it looks amazing. This is the most beautiful page ever. We're just gonna go back in and edit our permissions. So by default, Directus keeps everything secure, keeps a tight lid on everything. So this public policy that we have doesn't have any access to our data. So let's go in and add read access for organizations and let's let's set files as well in case we decide to upload some pictures of our amazing seat cushions that we're going to sell. And now if I refresh the page, we could see, great, I have a name, I have a website. Alright. That's kinda underwhelming. Not great. So let's have it design. Let's retray, here. We are going to create I'm gonna use Claude's sonnet, and let's create a landing page. You are let's let's back up a minute. What do we want our landing page to look like actually? Right? So we probably got like a hero. We've got a features for our seat cushions, seat cushions, hero section. And then we've got like a like a buy button. Buy button. Buy now. CTA. Alright. So that's gonna be the structure for our page. Here we go. We are going to flesh this out. You know, we probably want to you are are we gonna, like, one shot this? Let's see. Well, if I do this, you are a expert I I don't think you really need to do this because it's picking up up whatever I have, but create a hero section component for a online store that sells seat cushions to developers. A beautiful, well designed view three component using alright. So one of the features I've been experimenting with in cursor is this documentation feature. This starter has like the Nuxt UI library built into it. Which version am I actually running? Did I upgrade this to the latest one? Yeah. I'm running the alpha version. So we're gonna use those docs and tell when CSS. We'll see what we come up with here. Let's create a beautiful new component. You page hero. I don't know I don't know that I have any of these actually. Just you don't use our Nuxt UI components after all. Okay. So we can see what is coming up with hero section. We got a feature, ergonomic design. Yeah. I'm kinda curious to see what it comes up with as far as, like, the data model around this as well. We'll just go ahead and flush this out for it here while component section, features. Oh, this is running kinda slow. New collection, blah blah blah, right column. Yeah. It would probably even be easier just to go into, like, Tailwind UI and find some of these components here. They've got some nice ecommerce components. Let's look at it like a hero section. Alright. Let's just we'll just see what it came up with first and accept this. We'll go back to our organization. We'll insert this component in here. This is our hero section. Great. Cushion. JPEG. Is there a cushion dot JPEG? Hero section. Where is this cushion dot jpeg cushion hero dot jpeg. Alright. Let's bring in one of our first AI big guns here. We'll go to replicate, and I'm just gonna use our flux model here. It will create a product image of a futuristic seat cushion for developers if I could actually spell, that'd be dangerous. Developer's seat cushion, developer's desk chair. I don't think punctuation is hugely important here. Let's see what we come up with. For 6¢ an image. What are we gonna get out of this? That looks pretty pretty wicked awesome there. Right? So we're gonna download that. Let's dump this into our assets folder, and we'll call it seat cushion dot JPEG, and we'll just update that here. Alright. So this should be assets, images slash seat cushion. And oh, what have we got here? Something weird is going on. Better comfort for better code. There we go. Alright. Now we're getting somewhere, except this looks really odd with our price badge. Something's going on there. Let's just comment that out. There we go. We got our seat cushion. This is great. Alright. Now let's have it designed something else. Right? Let me just shrink this down just a little bit. Feature alright. So we want this to be our headline. Right? So let's flush this out a little bit more. This is gonna be our headline. This will be our description. I'm just trying to think through like our what our props are gonna look like for this. Define props, features as a feature. Great. Learn more, shop now. Better comfort for better code. This is a new collection. Badge. Alright. So we'll just stick that in our props. Now we got badge, got features. Do we actually want the icons we can. I think I've got the Nux icon library built into this so we could simplify this, like hero icons. There we go. I don't know what other hero cons we have here. Shopping bag, check circle. There we go. And then we'll, like, flesh this out. Where is that icon at? Icon. Feature dot icon. Yeah. So we could ditch all of this and make this a little bit cleaner. We'll keep that. Right? You icon. Name equals feature dot icon. We'll just ditch this, ditch that, clean this up a bit, and we should still have our icons. Great. And then we're gonna move out features out of here, we'll put that into this. So for now, we'll just say here's our data, our data. We'll drop our features here. Sometimes it is frustrating as I'll get out to properly just navigate using these AI tools. The tab tab tab is it's nice when it works well. When you have all these extensions included, it does get a little bit messy. Let's check on time. Where is Figma? Thirty seven minutes. Alright. Better get to it, g. Alright. If I hit refresh, are we actually going to let's call this data, and then we'll go back into our hero section. We'll just wrap all this up into data. There we go. There we go. Data dot badge, data dot headline, shop now, learn more, data dot features. Okay. So maybe that is a little long as far as a headline. What do we have previously? Yeah. Alright. Comfort for better code. There we go. Okay. Now, this is our data. Right? This is our data structure. Maybe we tell this to generate. Alright. So how are we gonna generate the actual code here? Like, how are we gonna generate the personalization of this specific page? Let's just ditch the code part. There's our website. Looks great. How are we gonna personalize this? So for that, let's kick off a Directus extension, basically. Basically. Yeah. Nothing basic about it. So what I'm thinking we'll do here, we'll set up a custom Directus extension so that whenever I am adding a new organization, it will create that data for us. So let's also do this where we'll go in and we'll call this just page data. Page data. Page content. It doesn't really matter what we call it. I'm just gonna set it to be JSON. That's what we're gonna ask back from the API. Alright. Let's kick off this extension. So I'm inside my Directus directory. We're probably gonna go into CD extensions within that. And then I'm gonna go n p x create direct us or create dash direct us dash extension latest. And I am going to create a let's do a custom hook. This is generate personalized page, custom landing page, AI landing page. We use TypeScripts. We'll go ahead and install the dependencies. And one of the things that I've got set up here inside my Docker Compose for this, obviously, like, I'm I'm I'm creating a volume for the extensions here so we could pull those in. But I'm also somewhere in here. I have extensions auto reload set so that whenever we build this extension, Directus is going to look for that and reload this extension or at least it should. So we'll go into CD AI landing page, npm dev. Alright. So let's actually open this bad boy up and see what we've got here. Items dot create. Okay. So now I'm just quickly going to cheat a bit and pull up the direct to stocks. Hooks, custom API hooks. So what we're looking for here is after this item is created, and I think the structure for a collection itself is a collection name dot items dot create. This is what we're gonna do. So our filter will look something like the or our action here will look something like this. We don't necessarily need this. Alright. So we're gonna say organizations dot items dot create, organization created, and this will be async. And what this is going to receive should be alright. We're gonna get the context here. We can see what that context is gonna look like. That's how we're gonna initiate some services. What does the action receive? Right? The action receives the event name and a callback function that is executed whenever the thing is submitted. Alright. Extensions guys. Do we have one on hooks? Use hooks to validate phone numbers. Items that create input collection. So we're gonna get the payload, I'm assuming, and the content, item context. Let's see just kinda what we get here. Extension's changed. Okay. Test httpstest.co. If I check my Docker logs, I cannot import. Let's just stop and spin up the Docker container one more time. Make sure we're actually getting that. Okay. I could see that extension being initialized. Oh my gosh. That gets ugly, doesn't it? Alright. Let's try this one more time. We'll delete testco, test Co. Are we seeing any console log? I'm not seeing any logs here. Async, define hook. Extensions reloaded. Organization oh, duh. You gotta use the right right syntax, Brian. Frustrating to be under the clock. Testtest.co. Hit save. Okay. So now we're seeing some stuff here. Great. Alright. There's our holy moly. Alright. So that is our there's the context that we're getting there. Organization created. There's the payload that we're receiving. And then we're getting the item context. Okay. Great. Alright. So what we're gonna do, what do we want to actually happen when this is going to pop off? There's a third party tool that we're gonna use for this called FireCrawl that I've been testing. Right? So let's try this. We're going to add Firecrawl. Js. Alright. So we're gonna go to our extension that we're running. I'm gonna install this library from FireCrawl. And we're gonna go ahead and one of the other things that I'm gonna do, we're gonna call this the organization's service. We're going to extract that out of the context. Const request. No. It's gonna be the services out of the context, then the item service through the services. And we're gonna call new item service. Great. And this is gonna give us the ability to update. Right? So we're gonna initialize that service. We've got that installed. Now let's copy our code here. I'm hoping this is my live API. New FireCrawl app. We need to import that. Scrape a single web page. Got it. We'll move that down below our item service, and we're gonna get the scrape result. And for now, let's just oh, I can already see the typo happening here. That's gonna be frustrating for me. And we're gonna say await updated org equals await organizationservice.update.one. Data, does that need to be wrapped in data? I don't know. Scrape content. Alright. We're gonna return the updated org, and let's wrap this in a try catch as well. Try catch. Console dot error. See if we get some formatting. Nice. Okay. Let's fire up the dev server for this and cross our fingers. Right? The other thing I need to update here, we're gonna have to go in and figure out which tab has all of my browsers in it. Maybe we just move that to a single browser for now. And we're gonna add a new field for this. We're gonna call it, scraped result. Scraped result. I don't know what this is gonna be. I'm assuming scraped content. I'm assuming this is gonna be JSON data that we're gonna get back. I guess I could look and see. Success data. You know, we could also just store the markdown. That might be easier. Where do we go? Scrape content. Let's delete that. Where does this store the markdown? Scraped. Scraped content. Alright. So according to FireCrawl, if we do this correctly, we're gonna get something like this. So with the scrape result dot data dot markdown. Fingers crossed. That's what we're gonna get. We could also just console log that to verify scrape content, scrape result. Alright. Let's go for it and see one last thing that I wanna do here. This is not, using, like, any of our accountability, so do not do this in production. But we'll just allow the public to create and update all the content on the underlying instance. Great. Love how secure I am being. I'm sure everybody on my team would be thrilled. Alright. So let's just go to Directus as the example. HTTPS, Directus.io. That's our website. Oh, I've already got directis.io hard coded in there as well, so we're probably gonna want to pick that up out of the payload as well. Can we still see that payload? No. Let's do this. We'll see the payload.website URL. We'll see if this actually works. Fingers crossed that it does. Scrape content. Save. What happens on this side of it? Around URL must be a top level domain or valid path. So I'm getting that error there. It's fine. Should set this up on update or create. Directus.io. Save and stay. Do we see what we get back? Is this thing still running in the background? What are we doing here? I got no visibility into what's happening here. Let's try it again. Directus. Directus. Io. Hit save. Must be a failed to scrape URL. URL must oh, duh, dummy. This is where it helps to define types so you don't make these same silly mistakes as I have. So I've called this field website. I was calling it website URL here, so not actually passing any website. Cannot read properties of collections. So there's our scrape results. Do we see the markdown? There's our markdown. Cannot update one. What am I doing wrong here? We're not updating the schema. We need to extension service, access items. Yes. Here we go. This is what I actually need to see. Alright. So we got our context. We're gonna do services get schema. We need that schema. And we're also gonna need the accountability schema. So in our item service definition, we don't wanna do this. We're gonna do this. Equals await. No AI. No. We're gonna await git schema. So we're gonna get the schema from our context and on the accountability side, accountability. That'll be accountability. If we just destructure that, I think that gives us what we need. Let's go back and try it again. Love hacking this stuff together on the fly. No pressure. Directus directus dot I o. Hit save and stay. Let's just watch over here and see what happens. Fire crawl seems to take a little bit, so that is forbidden. I don't know what we're getting over here. Can I just leave off the accountability object? How many times am I gonna create this before I just do update? Directus Directus dot I o. Save. Probably burning through these fire crawl credits as we speak as well. That that that that that, forbidden. You don't have permission to access this. Why is that not the case? What is the alright. So let's stop loading that. Let's just say console dot log the payload. Actually, I think it's I goofed up, didn't I? What are we gonna be receiving here? It's not gonna be it'll be payload dot key. Payload dot let's just log the whole payload again and see. Just comment out this. Comment out. Directus Directus dot I o slash payload key. Okay. Duh. You're smarter than that, Brian. Alright. So we need this key. That's what we're getting is the key payload dot key. So here, payload dot key. There's the event. There's the key. There's the organization of the collection we already got. Alright. Let's keep rolling and maybe try to actually complete this one. Directus. Directus dot I o. Save. Can we actually get the scrape content? Can we actually complete this on time? Can we do any of these things in any sort of actual working fashion? Is this actually gonna work? Will we know? How do I know? Console.logupdatedorg. Directus. Directus I o. Save. There's the payload. Fire crawl really takes a bit. Status code, 200. Updated org. Is this actually gonna see what we want? No. Of course not. It's not gonna update the right one. Data dot scraped content. I'm sure this is what we need to do here. Right? Update one. Let's look at the services. Update an item. Yep. It's not inside data. So I don't need that to wrap. Gosh. I'm just eating up all the time. I wish I spent more time with hook extensions. Super powerful because you're basically just updating the underlying Express app instance anyway. But alright. So now let's reach for anthropic. If we hit refresh, do we ah, still not getting the data that I want. Right? It's saying that it's updated that org. Scrape result. Scrape result scrape content. So they tricked me. It's not it's not as it shows. It's actually not there's actually no data attribute there. It's basically just scrape result dot markdown. Alright. Last freaking time for the scraped content, Directus Directus dot I o. I was not planning on doing this much troubleshooting. Behind the scenes here, I'm gonna go in and just create a API key for anthropic. Hundred apps. There's my API key. Updated org. Did we actually get what we want? Holy moly. We got some scraped content in here. Okay. Alright. So now the next step in the puzzle is going to be call the Anthropic API to generate a landing page for the organization with the JSON schema, page data. Alright. So now this is one of the things where I've been leaning on the Vercel API, or AI SDK. So I'm just gonna install it here, p m p I. This is just AI. And they've got a way. The last time I checked, the Anthropic does really well. Like, SONNET does really well at copywriting. But it doesn't have the JSON mode that the ones like OpenAI have. So I'm just gonna go in and look for provider management providers. Where are my providers? Providers and models. Looks for the anthropic provider. I'm gonna add it as well. And let's see what we can get here. Import anthropic. So I'm gonna import this guy. And then we're also going to do what? Create anthropic. We'll do that here. Now what I would normally do is this context object should have an e and v variables as well. API key. I'm not gonna do that here because I am worthless, basically. No. We're eating up a lot of time. Base URL, API key, generate text. We want to generate objects. So there's our anthropic client that we're creating. Don't mind that API key. Now let's define what do we need? We need Zod as well, p m Zod. And we're going to use was it generate object in here? See if we can find it. Generate object. Alright. Generate object from AI. Okay? Now what we're trying to do is just basically, we're gonna define a Zod schema of the object that we want, and that's gonna be our hero section. Right? Zod schema. We're gonna lean on the props. There we go. Okay. So now I'm just gonna copy this wholesale. We're gonna stick this in our custom hook. Again, not being careful at all about separation of concerns or cleanup. So there's our Zod schema. We want the object to return hero section schema. Alright. So now let's look up what we actually want this to how we're gonna work this. Generate object. We don't want testing. There's gotta be a better during text, during structured data. Alright. So our model okay. So we want the object equals await generate object. I'm hoping this is right. Fingers crossed with AI. Generate a landing page for the following organization with the content. Okay. For the organization payload. Name, the following content. You are an expert copywriter, and your job is to generate amazing landing pages that are personalized for our target clients. We sell the best desk chair cushions in the world for developers. Schema. There's our schema. That's our Zod model. Okay. When we get that back, what are we gonna do with the object? We are going to update the org, updated org two. It's fancy, fancy, fancy. Okay. Alright. How we doing on time? We got nine minutes to try and figure this out. Let's just PM, PM, dev this bad boy up and see if this is actually gonna come out at all. We're rebuilding this extension. Dun dun dun dun dun. I'm gonna nuke this entirely. Let's try it again. Let's see if it works for directus.io. We hit save. I could check the logs on Docker. Create anthropic is not defined. Anthropic. Response. Anthropic. Where is that? Providers and models. Anthropic provider. Create anthropic. Import the default provider. Oh, no. We could just import the what am I doing? Create create anthropic. Organizations. Oh, no. Directus. Duh. Directus .I o. Hit save. There's the payload. Obviously, it would be great to have visibility into this. And one tool that I've been using as of late is ingest. Great tool for something like this, generated hero section. This is gonna be nice, doc. Okay. Alright. So now before we reveal what it generated, let's just try to make sure this is actually gonna work. So instead of the data here, we're just gonna use the organization dot data dot page data. Organization dot page data. Generated hero section. That looks nice. Organization dot page data. Dun dun dun, the big reveal. Close that guy out. No. Status message. What is the status message? Did we actually get the page data generated? Okay. We got the page data generated. It looks like it's coming back with data here as well. So we should probably fix that in our hook. Page data page data is what? Object dot data. But for now, what I'm gonna do, I'm gonna just strip this out. Right? Great. And we refresh. We refresh. We refresh. No. What is going on? Organization. I'm excited for this, and I'm hoping we could get this to work. Right? Why am I not getting any of my data? Organizations. Access policies. We can see that organize oh, that's because it's not the right organization. Alright. I was using the old organization. We blew that one away like a hundred times. Right? This is probably where you'd wanna slug. Five minutes left. What do we have on the clock, Johnny? No. It's not working. Boy. Alright. There's our page data, organization dot page data. There's the scrape content. Why are we not seeing that? Right? Organization. Let's try it now. Status code. What is the error that we're receiving? V if organization dot page data. I could see the page data, man. Organization. Oh, duh. Gosh, man. What an idiot. Alright. So I I've done this on another episode as well. We're gonna transform this to get data. Where is this at? Is it here? Transform data. I don't know if this is how it functions. Error results, organization. I'm not sure the exact syntax, and I'm not gonna mess around with it. So we're gonna do this. It's gonna be organization. Boom. Bam. Directus plus Comfy Desk revolutionize your development experience, Seamless integration. Integrate Directus' flexible back end with your favorite front end while sitting comfortably on comfy desk cushions. Tailor your with adjustable cushions. Perfect. Alright. So now we have landing pages that are personalized for a specific client within, like an AI workflow. Right? So let's try this with some other company. Let's say OpenAI. I guess just to to pit these guys against each other here is this OpenAI.com. OpenAI Com. We'll hit save. And hopefully, this all runs, works nicely on the back end. There's the scrape result. You know, if I wanted to get really fancy, obviously, I could take this to the extreme here. But let's look at OpenAI. We'll view this on the website. What is going on? For noose proper next string, OpenAI. Okay. This one is not super strong. Right? Not sure what the scrape data result was. It looks like Firecrawl didn't do a great job with their website. Right? Let's try Apple.apple.com. Save. And we'll see what it comes back with. There's the scrape content. And, again, this is just coming back with markdown. You know, I might have better luck with, like, actual JavaScript parsing or something like that. But boom. Elevate your comfort coding experience with Apple inspired comfort, the iCushion Pro. Anyway, that's it for this episode. We've achieved this. I'm pushing a stop button on it. One minute left, we have basically fleshed out this personalized landing page where we add an organization, we use AI to scrape it, we then we generate content using LLMs, based on a specific schema, and then boom, we've got a personalized landing page that we could share with them. As far as next steps for me would probably be, like, setting this up on, like, a pretty URL or a slug, you know, adding this to some type of outbound, like, outreach campaign potentially. That's it though. It's amazing what you can put together in just an hour with tools like Cursor, Directus, Nuxt, Anthropic, all these different things come together to create stuff that's fun to build. I'll catch you on the next episode. Peace.","published",[135],{"people_id":136},{"id":137,"first_name":138,"last_name":139,"avatar":140,"bio":141,"links":142},"791e1503-1d88-463d-9347-0b9192933576","Bryant","Gillespie","9013afc8-e8d7-4182-9b18-44db08117bb9","Developer Advocate at Directus",[143,146],{"url":144,"service":145},"https://directus.io/team/bryant-gillespie","website",{"service":147,"url":148},"github","https://github.com/bryantgillespie",[],{"id":151,"number":152,"year":153,"episodes":154,"show":164},"d6b229fe-38fc-495b-ba0c-c574ebfea38f",3,"2025",[155,156,157,158,159,160,161,162,122,163],"ec88bef1-fffd-43eb-9d93-3123dc381b97","ab550907-1a5a-4fc0-8208-764465a1864f","97806b9d-063a-447f-9dca-617217ae5879","2a920d49-91e0-4237-bbd7-12e1181ad02a","fee34ecb-a4b6-4218-ac25-d15052c7604d","1ac7647d-0f09-4698-8ca0-e4448a4fe0e9","54789ca9-ca1d-4c25-a4d7-31c32de53d5d","09a64df3-79d6-4ede-a394-30a2499c5fee","36839053-13e7-4eb6-8e73-efb73bf61fb1",{"title":165,"tile":166},"100 Apps In 100 Hours","fb0f9d45-be21-4634-94d4-2ef1cc5146f2",{"title":8,"meta_description":8},{"id":169,"slug":170,"season":171,"vimeo_id":172,"description":173,"tile":174,"length":175,"resources":8,"people":8,"episode_number":176,"published":177,"title":178,"video_transcript_html":179,"video_transcript_text":180,"content":8,"seo":181,"status":133,"episode_people":182,"recommendations":186},"2c5b1e3e-c12f-4dc5-aef8-52082d41c192","new-years-resolution-bingo-generator","9095d401-66bc-416a-997b-f038365ce5ed","1163992739","Bryant is joined by Marc and Alvaro with the goal of building a goal bingo app in just 10 minutes using the MCP.","1e2aef3d-30ec-4672-be1e-f439efe7e045",18,1,"2026-03-02","New Years Resolution Bingo Generator","\u003Cp>Speaker 0: Alright, viewers. Welcome to, yet another episode of 100 app, 100 I don't know. No. No. No.\u003C/p>\u003Cp>One app in ten minutes. Right? We are doing the remix version today where we have ten minutes to build and plan plan and build an amazing app clone, crazy suggestion, and I have no idea what we're gonna do. So the rules. Right?\u003C/p>\u003Cp>Ten minutes to plan and build. No more, no less. How we're gonna do that? We are going to use some, amazing tools that we have built into Directus. And then, rule number two, the anti rule.\u003C/p>\u003Cp>Use whatever you've got at your disposal. Today, I've got two awesome dudes at my disposal, mister Alvaro and Mark from our team here at Directus. No strangers to the VUE community. Welcome to the show, gents.\u003C/p>\u003Cp>Speaker 1: Thanks for having us, Bryant.\u003C/p>\u003Cp>Speaker 2: Thank you very much for the nice intro. Happy, to be here.\u003C/p>\u003Cp>Speaker 0: Yeah. Yeah. No. I'm super excited. Have you guys given any thought to what we're what we're gonna build?\u003C/p>\u003Cp>Speaker 2: I think Mark has some idea though.\u003C/p>\u003Cp>Speaker 1: Yeah. So yesterday, we talked a little bit. I talked with Ava what we could build. And, I don't know if if I showed it to you, Brian, but on my website, I have a, instead of new year for solutions, I have new year's bingo cards. So you have five by five grid of stuff I want to do in the year.\u003C/p>\u003Cp>And if I get at least one in a row, so diagonal or horizontal or vertical, I already have bingo and it's a success. So I don't have to do all of them. And if you go to mark.dev/bingo\u003C/p>\u003Cp>Speaker 0: Okay. Let's check it out, guys.\u003C/p>\u003Cp>Speaker 1: You can it's still since it's just well, now February, not a lot has happened there. But\u003C/p>\u003Cp>Speaker 2: But it's a it's a really nice way to actually do some of the New Year's resolution. I always get the press at the end of the year like I have done, like, a quarter of them.\u003C/p>\u003Cp>Speaker 0: Yeah. I love it. Alright. So hey. This is neat, man.\u003C/p>\u003Cp>I I miss Yep.\u003C/p>\u003Cp>Speaker 1: And each of them can be either, like, you did it or you didn't do it or it can be progressive. Like, read six books and you are, like, one books, two books, three books in. And I think I also have, like, subtasks if we can make that work. Like, if one one, let's say, one bingo item has a few sub items as well. Like, don't have an example now, but that would also\u003C/p>\u003Cp>Speaker 0: be cool. Gotcha. Okay. New Year's resolution. Bingo card generator.\u003C/p>\u003Cp>Alright. That's what we're doing. This is gonna be amazing. This should be fun. What color are you guys feeling?\u003C/p>\u003Cp>Purple, pink?\u003C/p>\u003Cp>Speaker 2: I go I go purple. Blue. Oh, purple.\u003C/p>\u003Cp>Speaker 0: Purple. There we go.\u003C/p>\u003Cp>Speaker 1: Direct is purple. Nice.\u003C/p>\u003Cp>Speaker 0: Direct is purple. Alright, guys. Alright. So I'm sure you've seen the show. We're gonna start the clock.\u003C/p>\u003Cp>We got ten minutes to plan and build this thing. Let's do it. Alright. So, the first thing I usually do here is cover requirements. Right?\u003C/p>\u003Cp>So what are the requirements we need out of this? Right? We need to generate bingo cards. Like, what do you what were you calling those?\u003C/p>\u003Cp>Speaker 1: Like, items probably or\u003C/p>\u003Cp>Speaker 0: Okay.\u003C/p>\u003Cp>Speaker 1: Goals. Yeah.\u003C/p>\u003Cp>Speaker 2: Items. Yeah. Like a grid of of items.\u003C/p>\u003Cp>Speaker 1: Mhmm. Yeah.\u003C/p>\u003Cp>Speaker 0: Alright. So we got some goals. Those are what kinda fields are you tracking on those? Just the name of the goal?\u003C/p>\u003Cp>Speaker 1: Yeah. A name description and then the status.\u003C/p>\u003Cp>Speaker 0: Status of the goal. Progress. Progress. Is it are you status and progress interchangeable?\u003C/p>\u003Cp>Speaker 1: Yeah. I guess if you like the if the progress is under percent, the status\u003C/p>\u003Cp>Speaker 0: Okay. Yeah. Yeah. Yeah. Got it.\u003C/p>\u003Cp>Okay. And then we've got we've got goals. You've got what? Items underneath the goals? What do you do?\u003C/p>\u003Cp>We want, like, subtasks, like, if it's\u003C/p>\u003Cp>Speaker 1: You you can have subtasks. Let's see if there's one that has subtasks. I don't remember.\u003C/p>\u003Cp>Speaker 0: Tasks. It's called test. Alright. So the tasks would\u003C/p>\u003Cp>Speaker 1: play into into progress as well. I guess.\u003C/p>\u003Cp>Speaker 0: Into goal. And then the task completed increases progress. Cool. Alright. And task needs what?\u003C/p>\u003Cp>Name? Description? No. Just name? Date date probably.\u003C/p>\u003Cp>Speaker 1: Maybe the, the item can have a a completed ad. Yeah. They've completed as well for the task for the, item on top. Yeah.\u003C/p>\u003Cp>Speaker 0: Alright. And then we we wanna try to get a front end set up for this as well. Yeah. Alright. And we need a front end to display the bingo cards.\u003C/p>\u003Cp>Alright. This could be a stretch in seven minutes now. Let's see how we do. Alright. So what are we using today?\u003C/p>\u003Cp>Right? We've got a blank directus project. We've got Claude Code over here. Let's dive into it. Alright?\u003C/p>\u003Cp>I'm going to I'm not sure what you guys have been coding with. I've been using Super Whisper. I dig it. Hi. How are you doing?\u003C/p>\u003Cp>Alright, guys. We are building a New Year's resolution bingo card generator. I'm gonna copy and paste the data model that we want. You have access to a direct assistance. I want you to create our schema for that.\u003C/p>\u003Cp>We're also going to be building a front end to display the bingo cards. Let me know what questions you have. Let's create a plan. Alright. So this is crunching the transcript for that right now.\u003C/p>\u003Cp>Cool. There we go. I'll just, copy and paste this. Hopefully, we'll get some something good out of it. And we're gonna ask Claude Code to plan.\u003C/p>\u003Cp>Alright. So now we've got the schema. So we've got the direct us MCP connected to this thing. And I I think you guys have had a chance to try this out already. Right?\u003C/p>\u003Cp>Speaker 1: Yeah. I think Avro has. I haven't.\u003C/p>\u003Cp>Speaker 2: Yeah. Play with it in the morning. It's gonna create the collections, the schemas for you.\u003C/p>\u003Cp>Speaker 0: Yeah. Alright. So it's got a fresh direction. No custom collections. Alright.\u003C/p>\u003Cp>And I can zoom in just a little bit more so we could see this. What is the plan? And this is probably one of my favorite parts about this thing where it will prompt you for questions. Direct us flow, that's what we wanna do there. Vanilla JS.\u003C/p>\u003Cp>Yeah. That's what we'll do. What do you guys think? Five by five grid? Four by four?\u003C/p>\u003Cp>Speaker 1: We we can do also four by four so we don't have to come up with 25 things.\u003C/p>\u003Cp>Speaker 0: Amazing. Right? We got five minutes left.\u003C/p>\u003Cp>Speaker 2: You you can say to the MCP, hey, cloud, get, your twenty twenty six, bingo.\u003C/p>\u003Cp>Speaker 1: Oh, that was cool.\u003C/p>\u003Cp>Speaker 0: Yeah. Yeah. Alright. Public read, that's fine. Anyone can view those.\u003C/p>\u003Cp>Cool. Alright. And now, hopefully, this thing should have a plan.\u003C/p>\u003Cp>Speaker 2: I wonder which resolutions Cloud Code could have.\u003C/p>\u003Cp>Speaker 0: I don't know. Let's see. We'll we'll spin that up in an in a\u003C/p>\u003Cp>Speaker 1: new find out.\u003C/p>\u003Cp>Speaker 0: Alright. Cool. Right? Here's the direct to schema. There's our it's gonna create a flow.\u003C/p>\u003Cp>It's gonna create the front end. Sounds good. Let's let's roll with it. Right? I don't know what we're actually doing other than just talking this through here, but, I'm curious to see just how this thing works.\u003C/p>\u003Cp>I've you know, of course, like, spent a ton of time testing and building the MCP, but I've not spent a ton of time using it with, the latest Opus four five model. Alright. So it is checked the existing schema. Now we are it should start implementing. Yes.\u003C/p>\u003Cp>Please just start jamming on here. And if I refresh, now we should see some collections start to come in to the direct instance. We should see some collections. Start to come into the direct assistance. There we go.\u003C/p>\u003Cp>Okay. Alright. Oh, nice. I was just worried that I did something wrong. So we got our goals.\u003C/p>\u003Cp>We got our tasks. Amazing. Right? Now I could go in. We could potentially create some new ones if we need.\u003C/p>\u003Cp>One of the things that I like about this is it, like it seems like the anthropic models do a better job of, like, actually putting together a cohesive form than than, like, the OpenAI wants. So it's going through creating relations and fields. Alright, guys. So in this other one, create, some New Year's resolutions for yourself, Claude. Alright.\u003C/p>\u003Cp>You guys have any more guidance for this thing?\u003C/p>\u003Cp>Speaker 1: They should follow this the smart principle, probably.\u003C/p>\u003Cp>Speaker 0: Follow the smart principle. What's the smart principle?\u003C/p>\u003Cp>Speaker 1: Now you got me. So it's like measurable, achievable.\u003C/p>\u003Cp>Speaker 0: I know what you're talking about now. Yeah. The smart goals. Yeah. Yeah.\u003C/p>\u003Cp>And include the add them to the goals and tasks inside.\u003C/p>\u003Cp>Speaker 1: For the for me, the most important one is always measurable. You have to be able to measure what you do. If not, you lose yourself.\u003C/p>\u003Cp>Speaker 2: You lose yourself. That's so funny. It's okay.\u003C/p>\u003Cp>Speaker 0: That is very poetic. I love it, man. Alright. So it looks like okay. Yeah.\u003C/p>\u003Cp>I was just making sure we've got the relationship created correctly there. Alright. It is going to so we got two claws going. We got two minutes here. Let's see.\u003C/p>\u003Cp>I can see their goals and tasks.\u003C/p>\u003Cp>Speaker 1: Alright.\u003C/p>\u003Cp>Speaker 2: This is the next development, man. Right? Resting to\u003C/p>\u003Cp>Speaker 0: the next development. Yeah. This thing is going to yeah. I need to enter YOLO mode so we can actually, have this thing not stop to do these calls. But, behind the scenes, right, it is building this progress calculator flow.\u003C/p>\u003Cp>And and flows are\u003C/p>\u003Cp>Speaker 2: Yeah.\u003C/p>\u003Cp>Speaker 0: A a nice piece of functionality. It can be a little time consuming to set up, like, complex flows via the UI. So having direct us put these together, is, yeah, definitely time saving. Right? That's probably, like, five, ten steps there.\u003C/p>\u003Cp>Yes. Create those items. Alright. Let's see what we've got. Are we gonna get to the front end for this thing?\u003C/p>\u003Cp>I don't know if we are, man. I should've had Bryant. Should've had, Claude do that first. It's connecting the operations. Claude,\u003C/p>\u003Cp>Speaker 1: you need\u003C/p>\u003Cp>Speaker 0: to go faster, my friend. Alright. So what are the what are the goals that Claude set for itself? This should be interesting.\u003C/p>\u003Cp>Speaker 2: Put that description, Steven.\u003C/p>\u003Cp>Speaker 0: I'll reduce average response latency by 20%, Achieve 95% task completion rate without clarification. What an interesting goal. Here's the the individual tasks. And, I'll\u003C/p>\u003Cp>Speaker 2: And that was the end there. The front end.\u003C/p>\u003Cp>Speaker 0: Now it's doing it. No. Let me open this test project up. Is it going to have enough time? Yes.\u003C/p>\u003Cp>Proceed. New Year's resolution. Bingo. Oh, no. We ran out of time.\u003C/p>\u003Cp>So close. MCP connection should have access. No need to set up. I think, you know, this was so close, guys. I'm just going to it's against the rules, but you know what?\u003C/p>\u003Cp>We can make up our own rules here. I am just going to give access here to see and see if this will actually finish. Of course. There it is, man. The API permissions got us.\u003C/p>\u003Cp>We could see the bingo card here. There's the individual tasks. Ten minutes, full working back end with permissions, so close to a working front end. It did\u003C/p>\u003Cp>Speaker 1: pretty cool.\u003C/p>\u003Cp>Speaker 0: This is this is very cool. Right?\u003C/p>\u003Cp>Speaker 2: Even even with the subtask because that that wasn't an extra thing. Like, now it's the only iteration. Like, put the progress in the front end and\u003C/p>\u003Cp>Speaker 0: Yeah. I'm very curious to see. Right? It's already got, it looks like it maybe did it miss some of the flows? Right?\u003C/p>\u003Cp>So the thing to take away here is obviously, like, you could build incredibly quickly with Directus and MCP, and this is not loading, probably because of my computer. Just hates running all these Docker containers locally. What is going on?\u003C/p>\u003Cp>Speaker 2: How many do you have?\u003C/p>\u003Cp>Speaker 0: There's probably, like, five or 10 running at the moment, like, different instances. And I'm sure if I, like, killed the camera, it would probably stop doing this. I don't I don't know what's going on here. Local host, 8055. I at least wanna end this episode on a high note and show something.\u003C/p>\u003Cp>Come on.\u003C/p>\u003Cp>Speaker 1: Are you you're, are you running open claw? That's\u003C/p>\u003Cp>Speaker 0: I'm not yet. No. No. Not yet. I did test that thing out.\u003C/p>\u003Cp>It's, it's definitely an interesting one. I'm not sure that it is, it's not all there yet. Alright. It it's my testing was, like, most things you're gonna have to oh, great. Now I'm locked out of the actual instance as well.\u003C/p>\u003Cp>Hey. What is going on? Local host. 8055. Yeah.\u003C/p>\u003Cp>My open claw testing was basically, is it you're just gonna have to invest a lot of time into it to get something amazing out of it.\u003C/p>\u003Cp>Speaker 2: You you saw it. Right? Yeah.\u003C/p>\u003Cp>Speaker 0: Yeah. Alright. So we can see the flows. Did they yeah. It actually connected the flow.\u003C/p>\u003Cp>So I'm just curious. Right. Just wanting to see. Right? Build a mastering five new programming frameworks.\u003C/p>\u003Cp>Let's say we completed this right now. Does this flow actually work? And So it it it\u003C/p>\u003Cp>Speaker 2: could increase the progress of the task of the goal.\u003C/p>\u003Cp>Speaker 0: It should. And, of course, doing a hard refresh here is not not a great idea. Alright. Well, gents, you know, I'm not sure whether to put a, like, a thumbs up stamp on this one. Thumbs up stamp.\u003C/p>\u003Cp>We can just do I think. Yeah. This was, I think we got most of the functionality\u003C/p>\u003Cp>Speaker 2: there. Good at dive.\u003C/p>\u003Cp>Speaker 0: We just didn't get, the front end all the way there.\u003C/p>\u003Cp>Speaker 1: Oh, Brian, you are lagging quite.\u003C/p>\u003Cp>Speaker 0: Of course, it did.\u003C/p>\u003Cp>Speaker 1: Is it done? I think you you get a a thumbs up, Brian, because it we got a working thing at the end, and you had the the grid showing everything with the progress. So I think you get a thumbs up.\u003C/p>\u003Cp>Speaker 0: Yeah. Alright, guys. My computer is struggling, so we are going to sign off for this episode. Mark Alvaro, I've heard a little rumor that there might be a podcast coming up, so I'm super excited for that. Thanks for joining me for this episode of one app in ten minutes.\u003C/p>","Alright, viewers. Welcome to, yet another episode of 100 app, 100 I don't know. No. No. No. One app in ten minutes. Right? We are doing the remix version today where we have ten minutes to build and plan plan and build an amazing app clone, crazy suggestion, and I have no idea what we're gonna do. So the rules. Right? Ten minutes to plan and build. No more, no less. How we're gonna do that? We are going to use some, amazing tools that we have built into Directus. And then, rule number two, the anti rule. Use whatever you've got at your disposal. Today, I've got two awesome dudes at my disposal, mister Alvaro and Mark from our team here at Directus. No strangers to the VUE community. Welcome to the show, gents. Thanks for having us, Bryant. Thank you very much for the nice intro. Happy, to be here. Yeah. Yeah. No. I'm super excited. Have you guys given any thought to what we're what we're gonna build? I think Mark has some idea though. Yeah. So yesterday, we talked a little bit. I talked with Ava what we could build. And, I don't know if if I showed it to you, Brian, but on my website, I have a, instead of new year for solutions, I have new year's bingo cards. So you have five by five grid of stuff I want to do in the year. And if I get at least one in a row, so diagonal or horizontal or vertical, I already have bingo and it's a success. So I don't have to do all of them. And if you go to mark.dev/bingo Okay. Let's check it out, guys. You can it's still since it's just well, now February, not a lot has happened there. But But it's a it's a really nice way to actually do some of the New Year's resolution. I always get the press at the end of the year like I have done, like, a quarter of them. Yeah. I love it. Alright. So hey. This is neat, man. I I miss Yep. And each of them can be either, like, you did it or you didn't do it or it can be progressive. Like, read six books and you are, like, one books, two books, three books in. And I think I also have, like, subtasks if we can make that work. Like, if one one, let's say, one bingo item has a few sub items as well. Like, don't have an example now, but that would also be cool. Gotcha. Okay. New Year's resolution. Bingo card generator. Alright. That's what we're doing. This is gonna be amazing. This should be fun. What color are you guys feeling? Purple, pink? I go I go purple. Blue. Oh, purple. Purple. There we go. Direct is purple. Nice. Direct is purple. Alright, guys. Alright. So I'm sure you've seen the show. We're gonna start the clock. We got ten minutes to plan and build this thing. Let's do it. Alright. So, the first thing I usually do here is cover requirements. Right? So what are the requirements we need out of this? Right? We need to generate bingo cards. Like, what do you what were you calling those? Like, items probably or Okay. Goals. Yeah. Items. Yeah. Like a grid of of items. Mhmm. Yeah. Alright. So we got some goals. Those are what kinda fields are you tracking on those? Just the name of the goal? Yeah. A name description and then the status. Status of the goal. Progress. Progress. Is it are you status and progress interchangeable? Yeah. I guess if you like the if the progress is under percent, the status Okay. Yeah. Yeah. Yeah. Got it. Okay. And then we've got we've got goals. You've got what? Items underneath the goals? What do you do? We want, like, subtasks, like, if it's You you can have subtasks. Let's see if there's one that has subtasks. I don't remember. Tasks. It's called test. Alright. So the tasks would play into into progress as well. I guess. Into goal. And then the task completed increases progress. Cool. Alright. And task needs what? Name? Description? No. Just name? Date date probably. Maybe the, the item can have a a completed ad. Yeah. They've completed as well for the task for the, item on top. Yeah. Alright. And then we we wanna try to get a front end set up for this as well. Yeah. Alright. And we need a front end to display the bingo cards. Alright. This could be a stretch in seven minutes now. Let's see how we do. Alright. So what are we using today? Right? We've got a blank directus project. We've got Claude Code over here. Let's dive into it. Alright? I'm going to I'm not sure what you guys have been coding with. I've been using Super Whisper. I dig it. Hi. How are you doing? Alright, guys. We are building a New Year's resolution bingo card generator. I'm gonna copy and paste the data model that we want. You have access to a direct assistance. I want you to create our schema for that. We're also going to be building a front end to display the bingo cards. Let me know what questions you have. Let's create a plan. Alright. So this is crunching the transcript for that right now. Cool. There we go. I'll just, copy and paste this. Hopefully, we'll get some something good out of it. And we're gonna ask Claude Code to plan. Alright. So now we've got the schema. So we've got the direct us MCP connected to this thing. And I I think you guys have had a chance to try this out already. Right? Yeah. I think Avro has. I haven't. Yeah. Play with it in the morning. It's gonna create the collections, the schemas for you. Yeah. Alright. So it's got a fresh direction. No custom collections. Alright. And I can zoom in just a little bit more so we could see this. What is the plan? And this is probably one of my favorite parts about this thing where it will prompt you for questions. Direct us flow, that's what we wanna do there. Vanilla JS. Yeah. That's what we'll do. What do you guys think? Five by five grid? Four by four? We we can do also four by four so we don't have to come up with 25 things. Amazing. Right? We got five minutes left. You you can say to the MCP, hey, cloud, get, your twenty twenty six, bingo. Oh, that was cool. Yeah. Yeah. Alright. Public read, that's fine. Anyone can view those. Cool. Alright. And now, hopefully, this thing should have a plan. I wonder which resolutions Cloud Code could have. I don't know. Let's see. We'll we'll spin that up in an in a new find out. Alright. Cool. Right? Here's the direct to schema. There's our it's gonna create a flow. It's gonna create the front end. Sounds good. Let's let's roll with it. Right? I don't know what we're actually doing other than just talking this through here, but, I'm curious to see just how this thing works. I've you know, of course, like, spent a ton of time testing and building the MCP, but I've not spent a ton of time using it with, the latest Opus four five model. Alright. So it is checked the existing schema. Now we are it should start implementing. Yes. Please just start jamming on here. And if I refresh, now we should see some collections start to come in to the direct instance. We should see some collections. Start to come into the direct assistance. There we go. Okay. Alright. Oh, nice. I was just worried that I did something wrong. So we got our goals. We got our tasks. Amazing. Right? Now I could go in. We could potentially create some new ones if we need. One of the things that I like about this is it, like it seems like the anthropic models do a better job of, like, actually putting together a cohesive form than than, like, the OpenAI wants. So it's going through creating relations and fields. Alright, guys. So in this other one, create, some New Year's resolutions for yourself, Claude. Alright. You guys have any more guidance for this thing? They should follow this the smart principle, probably. Follow the smart principle. What's the smart principle? Now you got me. So it's like measurable, achievable. I know what you're talking about now. Yeah. The smart goals. Yeah. Yeah. And include the add them to the goals and tasks inside. For the for me, the most important one is always measurable. You have to be able to measure what you do. If not, you lose yourself. You lose yourself. That's so funny. It's okay. That is very poetic. I love it, man. Alright. So it looks like okay. Yeah. I was just making sure we've got the relationship created correctly there. Alright. It is going to so we got two claws going. We got two minutes here. Let's see. I can see their goals and tasks. Alright. This is the next development, man. Right? Resting to the next development. Yeah. This thing is going to yeah. I need to enter YOLO mode so we can actually, have this thing not stop to do these calls. But, behind the scenes, right, it is building this progress calculator flow. And and flows are Yeah. A a nice piece of functionality. It can be a little time consuming to set up, like, complex flows via the UI. So having direct us put these together, is, yeah, definitely time saving. Right? That's probably, like, five, ten steps there. Yes. Create those items. Alright. Let's see what we've got. Are we gonna get to the front end for this thing? I don't know if we are, man. I should've had Bryant. Should've had, Claude do that first. It's connecting the operations. Claude, you need to go faster, my friend. Alright. So what are the what are the goals that Claude set for itself? This should be interesting. Put that description, Steven. I'll reduce average response latency by 20%, Achieve 95% task completion rate without clarification. What an interesting goal. Here's the the individual tasks. And, I'll And that was the end there. The front end. Now it's doing it. No. Let me open this test project up. Is it going to have enough time? Yes. Proceed. New Year's resolution. Bingo. Oh, no. We ran out of time. So close. MCP connection should have access. No need to set up. I think, you know, this was so close, guys. I'm just going to it's against the rules, but you know what? We can make up our own rules here. I am just going to give access here to see and see if this will actually finish. Of course. There it is, man. The API permissions got us. We could see the bingo card here. There's the individual tasks. Ten minutes, full working back end with permissions, so close to a working front end. It did pretty cool. This is this is very cool. Right? Even even with the subtask because that that wasn't an extra thing. Like, now it's the only iteration. Like, put the progress in the front end and Yeah. I'm very curious to see. Right? It's already got, it looks like it maybe did it miss some of the flows? Right? So the thing to take away here is obviously, like, you could build incredibly quickly with Directus and MCP, and this is not loading, probably because of my computer. Just hates running all these Docker containers locally. What is going on? How many do you have? There's probably, like, five or 10 running at the moment, like, different instances. And I'm sure if I, like, killed the camera, it would probably stop doing this. I don't I don't know what's going on here. Local host, 8055. I at least wanna end this episode on a high note and show something. Come on. Are you you're, are you running open claw? That's I'm not yet. No. No. Not yet. I did test that thing out. It's, it's definitely an interesting one. I'm not sure that it is, it's not all there yet. Alright. It it's my testing was, like, most things you're gonna have to oh, great. Now I'm locked out of the actual instance as well. Hey. What is going on? Local host. 8055. Yeah. My open claw testing was basically, is it you're just gonna have to invest a lot of time into it to get something amazing out of it. You you saw it. Right? Yeah. Yeah. Alright. So we can see the flows. Did they yeah. It actually connected the flow. So I'm just curious. Right. Just wanting to see. Right? Build a mastering five new programming frameworks. Let's say we completed this right now. Does this flow actually work? And So it it it could increase the progress of the task of the goal. It should. And, of course, doing a hard refresh here is not not a great idea. Alright. Well, gents, you know, I'm not sure whether to put a, like, a thumbs up stamp on this one. Thumbs up stamp. We can just do I think. Yeah. This was, I think we got most of the functionality there. Good at dive. We just didn't get, the front end all the way there. Oh, Brian, you are lagging quite. Of course, it did. Is it done? I think you you get a a thumbs up, Brian, because it we got a working thing at the end, and you had the the grid showing everything with the progress. So I think you get a thumbs up. Yeah. Alright, guys. My computer is struggling, so we are going to sign off for this episode. Mark Alvaro, I've heard a little rumor that there might be a podcast coming up, so I'm super excited for that. Thanks for joining me for this episode of one app in ten minutes.","0878a4f4-5836-4a78-b897-a8b4789c9e7c",[183,184,185],"851de303-b434-4092-8b15-fb6720b1e4c2","010213cf-c50a-4f60-b264-afb8fcf3e4b3","487b9dd3-5c6e-4894-bf34-a2bb1f6d2b64",[],{"reps":188},[189,245],{"name":190,"sdr":8,"link":191,"countries":192,"states":194},"John Daniels","https://meet.directus.io/meetings/john2144/john-contact-form-meeting",[193],"United States",[195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244],"Michigan","Indiana","Ohio","West Virginia","Kentucky","Virginia","Tennessee","North Carolina","South Carolina","Georgia","Florida","Alabama","Mississippi","New York","MI","IN","OH","WV","KY","VA","TN","NC","SC","GA","FL","AL","MS","NY","Connecticut","CT","Delaware","DE","Maine","ME","Maryland","MD","Massachusetts","MA","New Hampshire","NH","New Jersey","NJ","Pennsylvania","PA","Rhode Island","RI","Vermont","VT","Washington DC","DC",{"name":246,"link":247,"countries":248},"Michelle Riber","https://meetings.hubspot.com/mriber",[249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,226,437,438],"Albania","ALB","Algeria","DZA","Andorra","AND","Angola","AGO","Austria","AUT","Belgium","BEL","Benin","BEN","Bosnia and Herzegovina","BIH","Botswana","BWA","Bulgaria","BGR","Burkina Faso","BFA","Burundi","BDI","Cameroon","CMR","Cape Verde","CPV","Central African Republic","CAF","Chad","TCD","Comoros","COM","Côte d'Ivoire","CIV","Croatia","HRV","Czech Republic","CZE","Democratic Republic of Congo","COD","Denmark","DNK","Djibouti","DJI","Egypt","EGY","Equatorial Guinea","GNQ","Eritrea","ERI","Estonia","EST","Eswatini","SWZ","Ethiopia","ETH","Finland","FIN","France","FRA","Gabon","GAB","Gambia","GMB","Ghana","GHA","Greece","GRC","Guinea","GIN","Guinea-Bissau","GNB","Hungary","HUN","Iceland","ISL","Ireland","IRL","Italy","ITA","Kenya","KEN","Latvia","LVA","Lesotho","LSO","Liberia","LBR","Libya","LBY","Liechtenstein","LIE","Lithuania","LTU","Luxembourg","LUX","Madagascar","MDG","Malawi","MWI","Mali","MLI","Malta","MLT","Mauritania","MRT","Mauritius","MUS","Moldova","MDA","Monaco","MCO","Montenegro","MNE","Morocco","MAR","Mozambique","MOZ","Namibia","NAM","Niger","NER","Nigeria","NGA","North Macedonia","MKD","Norway","NOR","Poland","POL","Portugal","PRT","Republic of Congo","COG","Romania","ROU","Rwanda","RWA","San Marino","SMR","São Tomé and Príncipe","STP","Senegal","SEN","Serbia","SRB","Seychelles","SYC","Sierra Leone","SLE","Slovakia","SVK","Slovenia","SVN","Somalia","SOM","South Africa","ZAF","South Sudan","SSD","Spain","ESP","Sudan","SDN","Sweden","SWE","Tanzania","TZA","Togo","TGO","Tunisia","TUN","Uganda","UGA","United Kingdom","GBR","Vatican City","VAT","Zambia","ZMB","Zimbabwe","ZWE","UK","Germany","Netherlands","Switzerland","CH","NL",1773850451211]