Hop along with Bryant as he attempts to build a management system for AI-generated rabbit avatars ("Rabbitars"). Watch him tackle importing hundreds of images, setting up trait relationships, and creating an automated flow to generate new characters with DALL-E—all in just 60 minutes.
Speaker 0: Alright. Alright. Alright. Welcome back to yet another episode of 100 apps, one hundred hours. I'm your host Brian Gillespie, and this is the show where we try to build or rebuild some of your favorite apps or even crazy off the wall app ideas in one hour or less.
Today, we've got a fun episode for you, an AI Rabatar directory, and I'll explain what that means in just a moment. But, the rules, if you're new to the show, you have sixty minutes to plan and build an application, no more, no less, and we're gonna use whatever tools we have at our disposal, which for me lately has, been a bit of, like, Cursor AI, the, AI enabled IDE. Been using it. I like it a lot for auto completion and things like that. Also, we've got some pieces for this one from a previous project.
So the AI Ravitar directory. Let's take a look at at what we've got. Right? So this is a concept that we had in our Leap Week registration system. So for Leap Week three, back in the summertime, you could go in and when you registered, you could generate an AI Ravatar, that filled your astronaut suit.
This was a space theme. You pick your traits, and it would generate a custom Ravatar for you that we then use in, like, the OG images on the the actual ticket pages. So lots of cool stuff there. But, what we're gonna do today is take this and transform it into a directory of these Ravatars with their traits that we could potentially reuse somewhere else. So with that, let's start the clock and dig into this thing.
What is the actual functionality that we want out of this? And, you know, this is usually where I like to start anytime I'm building an application. We're just gonna do this. And did we yep. Okay.
Alright. So the functionality that we want out of this. Right? We want a list of well, basically, manage a lot of rabbitars. So we wanna be able to, you know, edit those, generate them.
Let's say generate new rabbitars based on a prompt, and, you know, manage traits. Manage a lot of rabbitars. You know? Do we get potentially, like, serve random rabbitars? I don't know.
Serve random Ravitar based on a seed. Alright. So what is our data model for this thing looks like? Hey. This is one that I'm kind of building on the fly here.
I haven't really thought much about this. You know, some of the other ones, I think a a little more about before we pop in here, but, obviously, we're gonna have our rabbitars as the top level. If we drill down into that, what does that actually look like? We've got, a relationship to traits that we'll have. We probably got a title for the Ravitar.
We probably have a description. If I remember this right, maybe we call it, like, prompt because that's what we had from our Leap Week setup. And then we've got a list of traits, and we can make those relational. So we'll have that. We'll just connect the dots there.
That'll be a mini to mini relationship. Right? Mini to mini relationship between traits and Ravatars, and this will just have a trait. And, you know, maybe we can add a description to that if we want to. No big deal.
No big deal either way. This looks pretty good. You know, if you watched the show before, I've I've got, like, a Nuxt app starter that I use from time to time. I've downloaded a list of the files and prompts from our Leap Week system and, you know, anonymize this data so that it is secure. And then we've just created a blank project on Directus cloud.
You can see there's a totally blank instance. So let's dive right in. Right? The first thing we're gonna do, let's create our Ravatar collection. Right?
So we're gonna call this Ravatars. For the primary key, let's use a generated UUID for this, and we'll have a created at. We can say created by, or we could just use the naming convention that we have here. This is one of my favorite features inside Directus. Like, you can adjust these, but, basically, this will give you, you know, the standard time stamps, the standard relationship to the user that created these things.
We don't really need a status for these. Right? Once they're created, they're created. We don't need a sort. So let's just add that.
There we go. We've got our avatars and now we're gonna create these extra fields like title, prompt, and then we'll go through and do the traits. Right? So let's actually change this to a name. We'll give each one of these Ravatars a name somehow.
Maybe we could use AI to do that since this is an AI generated episode. Great. Cool. Well, now we've got a name. Pretty simple.
Just a string input. What else do we have? We have a prompt. You know, what was the actual prompt that we used to generate this avatar? That could be handy information.
What else? And then we need the actual avatar. So we need the file. Forgot to do that one, didn't I? So let's do the file.
I could use file or image here. It's the same kind of relationship. It just depends on what type it is. So if it's an image, which we are doing images, I would choose the image interface here because it will show, like, a nice thumbnail preview. So we're just gonna call this the file for the avatar or ravitar, and we can add padding to this if we need to.
Great. Now let's work on traits. Right? So traits is gonna be a separate collection for me just because I want to be able to add new traits easily and, you know, be able to query the number of rabbitars based on a trait. And that gets a little trickier to do if you're using, you know, traits here as a a field in, like, CSV format.
So I'm just gonna create a new table. We're gonna call it traits. And instead of the primary key field being ID with, like, an auto incremented integer here, I'm just gonna do this. Let's call the primary key field trait, and we're gonna use a manually entered string. That'll be nice.
You know, created at, created by, updated at. I really don't need this, but we'll add it anyway. Great. And now we've got a trait field or trait collection, I should say. And, you know, I could go through and add a description to this if I wanted to, you know, just extra info, really.
Alright. And and I could even go as far as, like, using a label. So where I'm using this as the primary key, you know, I might want to, like, slugify that or make sure that it everything is, like, in camel case or something like that. But cool. So you see how easy it is to add these extra fields to direct us.
Let's do, cruelty free. Yeah. That's my favorite icon. I don't know why this is called cruelty free, but that gets us the bunny that we're looking for. Awesome.
And then we'll add traits. I don't know if there's an icon for this or not. Traits attributes. Looks good enough. Attributes.
Where are you? There we go. Alright. Just a little little touch of OCD there. Cool.
So now we've got avatars. We can see we got a name. We got a prompt. We got a file. We got traits.
But these two are not linked together. Right? So, what we want to do next is just link these two together. That is going to be using a many to many relationship inside Directus and I'm going to call this field traits. So, you can see I'm in the Ravatars collection.
I'm going to go in and add a new field called traits and the related collection is going to be traits. And what I'm going to do here, we'll show a link to that, but for now what I'm going to do is continue in advanced field creation mode. And we're gonna go to the relationship. So here, we can see that Directus is gonna create a junction table for us. Let's call it ravitar traits, and I'm gonna change the fields inside that collection.
So this will be called ravatar. This will be called trait. And we can add that corresponding field to the traits collection as well. That way I can look at any of the ravatars that have a trait. And I guess we can add a sort field here.
So the relational triggers, if I bring up my little mouse pointer tool here, it's called mouse posay, by the way. If you are interested in this little thing that you've you've caught me use a couple times, Mouse Pose if you're on a Mac. Pretty neat little piece of software for creating videos or doing training. Alright. Back to the lecture at hand.
So we will go in and these relational triggers are just whenever these certain events happen. And, basically, if I deselect a trait on a Ravatar or I delete a trait, what happens? And more times than not, when I'm using many to many relationships, I set these up so that, it will delete the junction table item because I I still have the data in each individual collection. Cool. So with that, let's go ahead and create this mini to mini relationship.
And now I can see the traits here. I've got traits there. And you can see inside the data model that junction table that was created, ravitar traits. So, you know, if I open this up and I create a a new ravitar, right, we can add existing traits, add new traits, blah blah blah blah blah blah blah blah blah. Alright.
So now what I've got working with here is this should be set up correctly for this kind of data model. Right? And this is ripped out of our Leap Week project that I was talking about that I won't showcase here, but you can get access to something similar inside our Directus plus subscription. It's called the event registration kit, and it comes with a a NUCs front end with the, like, the detailed badges and things like that. But we got the file.
We've got the prompt. We've got the individual traits that should have the correct keys to a trait. I wanna say that will create the trait, but we'll take a look once we actually figure that out or not. And this may throw an error when we try to import it. But for now, like, what I'm concerned with is this file.
Right? If I look inside this project, I don't have any files. So what I've done in another directory here, I've used our template CLI tool to just export all the files and assets from that project. So here we go. I've got all the actual rabbitars here.
We could see what all those fine fellows look like and and ladies. Let's try to use the Directus template CLI tool to get those into this project. So we got rabbitars.directus.app. We're gonna go in to my users here. I'm gonna create a token for this.
We'll save that token. And what do I wanna do? We're gonna go to c d desktop /leapweek. Do we have something there? We got templates.
Okay. Good. Let's c d into templates. We got the Leap Week template. And now we're gonna do, let's actually just pull this thing up so we can see what's going on.
Template CLI. Open that up in a new tab. Got this going on. Alright. So the latest version of this does have, like, a programmatic mode where I can apply partials.
So I'm gonna just copy this into my editor. We're gonna go h t t p s, what is this? Ravatars.directus.app. I'm gonna paste my token. Reminder to self roll this token before we do this.
My template is leap week. Template type equals local. I'm gonna do a partial, and we're gonna do files. So that flag should get us, oh, and I think partial is, like, the p part of it as well. Is that what that stands for?
P is a partial? Partial apply p. Okay. So we wanna do files only. Fingers crossed if this is actually gonna work or not.
That's the beauty of this sort of thing. Alright. We hit go. It's logged in as the admin user. This doesn't look like it's doing what we want.
Row row, Raggy. Maybe loading the files, and then we may be having to do some cleanup work after the fact. So I probably lied about a flag here or something. Well, let's just open it up and see. It's always fun.
What else has this done for us? We'll just make this full screen again. Rabbitars. And it is uploading the files here, so we're probably getting a bit of that. And you could see now we do have events.
We we've got this entire Leap Week template, which, is grand. So we'll we'll let this process these files, I guess, before we try to do anything else. This is gonna eat up some time on the clock, I'm afraid. I don't know how we're going here. One of the the nice things that we have recently added in Directus is the ability to see the logs.
So these are coming in real time, and I could see, all the logs that are coming in. And you could see that we've got files here. So it should be uploading these files. And if I open this tab, you know, we should start to see some of those files uploading. But this is just a handy way to check on what's happening inside the direct us instance in real time.
Now the template CLI tool that I've got here, it has a rate limit of, like, 10 requests a second in here. So that's why you're seeing, like, these things being staggered, which is helpful to not kind of overload. And these are not small files either. So this is a lot of bandwidth that I'm eating up here. But now you can start to see some of the the actual avatars.
We just hope that the import of the JSON goes well once this is done. Now, maybe we try to work on some other piece of this while this is loading. I can't imagine how long this is gonna take. There's 924. We're doing 10 a second times 924 divided by 10.
That gives us a 92 divided by 60. Minute and a half. It's taking a little longer than that, isn't it? Anyway, let's dive in and I don't think it's going to mess up if we start cleaning this up, but it's a risky run. Right?
I'm gonna start deleting these collections that I did not actually need in this case. And then I'm gonna go back to the drawing board at some point after this and figure out why that partial apply did not work. Still loading files, people, ravatar. We don't need any of these blocks. We're just gonna clean this up.
And again, what Directus is doing underneath the hood here, it has basically added these tables to my SQL database. But once I, you know, delete these or add new collections or any changes that I make through Directus through the studio, the underlying Directus APIs are making those changes to the SQL database in real time, which is nice. Right? So if I were to take a look now, like, all these tables would be in my SQL database, but we're just gonna clean these up. Who said this is not fun?
Make sure we're not removing the fields that we actually need for this. Still loading files. Still loading files. Alright. Delete.
Delete. Delete. And this is how you know that these things aren't scripted because if it was, I would be way more organized than this. Alright. So now we've got our collections back where we need it.
Are we we're still getting all the files in here? Files. Files. Files. Files.
Files. Just posting away. Anyway, let's try to figure out what we're gonna do next. Right? We've got the av Ravatars in there.
We're gonna wanna generate new Ravatars at some point. How can we do that? Right? For that, let's go into the marketplace. And I believe we have an AI image generation option.
Yes. Or operation here. So this is part of the Directus AI pack that we have. We've got the AI image generation option which calls DALL E three to generate an image. Right?
So let's install this guy. We'll refresh. That will pull up that. Are we done with the files? No.
We are not. There's another one that I'm gonna pull in here, the AI writer operation. So this is basically just a shortcut for the different AI LLM providers like OpenAI, Anthropic, Meta, Llama, all those different ones. And you can use a couple different options here. So we're just gonna install this too in case we need that.
And let's talk about, like, creating new Revatars. We'll refresh. Still plugging away on the images. Man, how many rabbitars worth this in in in total? Let's let's just see.
924 Ravatars. We're awaiting more logs. Are we done? Post. Post.
I don't see oh, there we go again. Coming back. We're running more images. But, yeah. You can actually see the scalability here.
Like, we're just hammering this thing with images and everything else is running a okay. Alright. So let's tackle this Gravatar generation piece. Right? If I want to create a new Ravitar, right, we're probably going to pass it some traits.
And maybe we give it a name. Right? So let's organize this just a little bit because the two things that I want are gonna be up here. Like, I'm not gonna give this a prompt each time. I just want to store the prompt that was used to generate that.
And we may even have something like this, like a metadata field. I I use this pattern a lot as well where I just store some JSON data that comes back from these. Alright. So basically, we'll give it a name, we'll add a few traits, and then we will store the rest of this info. And we could even go in and add, like, a group to this, like a detail group.
Yeah. We'll call this generation, AI generation. Great. Do we have, like, a little robot icon? Perfect.
Cool. So now we can just stuff all these in here, Get a little bit of organization. And we might want to even like update a status or something like that. Right? I didn't think we needed a status field here, but maybe we do wanna have a status for, like, generating or generation.
Maybe we won't mess with that at this moment. Alright. Okay. So it looks like it's got all the files. That's all we need.
I'm just gonna cancel that. Do we have 924 files? Is that what it shows? Let's see. All files.
Refresh. We're done sending files through here. Boom. Boom. Boom.
Boom. Oh, have I somehow logged myself out? No. Okay. I don't know what happened there.
Alright. So we do have 924 files. Great. We'll take a detour again from this. But now we've got, like, this nice AI generation thing that, you know, we could see, like, the actual file.
Maybe we wanna pull a file back out of this. K. I'm sorry. I'm a bit scattered here. I haven't had enough coffee yet this morning.
Alright. So now I've got this JSON file that I exported from, the the directory, the Leap Week. Let's go in and actually try to import this file. We'll go to Directus, hundred apps, Nuxt starter. I've got output dot JSON.
Let's open this up and see if we can get this imported. It says invalid foreign key. That's not good. Should we run this type of script again? Trait.
Let's just go in and create a rabbitar. Let's create this first one. File. Trait. Where's our file?
Oh, I'm inside traits. Did I import inside the trait directory? Maybe that could be the problem. We'll just edit the raw value. Let's add the file there.
That should find the file. We don't have any of these traits, so we'll create one. Sunglasses. Masculine. Serious.
Great. Beard and mustache. And if I add this prompt there we go. Alright. So I'm just going to delete this guy from our file since we're adding that now.
We'll hit save and stay. Now we've got our our actual file here. We've got the list of prompts or traits. Serious rabbit face. Mcrabbit.
Serious rabbit face Mcrabbit. There's our directory of, this guy. We can see we've got the traits now, and we're showing, like, the actual rabbitars that we have here. And there's the list of traits. Great.
Cool. Makes sense. And then we could even clean that up a bit if we wanted to, but let's now let me try to import this again just to see. I think I may have had the wrong directory. Invalid foreign key.
Alright. Let's see. Let's try this again. We'll hit start import. What are we getting back from the for the trait collection, Ravitar traits?
Invalid foreign key in Ravitar traits. It's always always fun. Alright. So what I'm gonna do, I'm gonna just open up this inside a new tab. I'm gonna wanna wanna see the data we're getting back from the API.
Right? So here I could see this is the actual data. Let's do something like this where we add an asterisk, we get fields, we get traits, and I just wanna get all the root level fields for traits. There's the trait. I guess, do we have to go through and get all the individual traits?
Is that the problem? It should be this should be the right syntax. Alright. I got this script. Where is this guy?
So we're transforming the snake case. Trait. Trait. We shouldn't have to do that, should we? Alright.
Let's think about this a little bit further. Do we need to stuff this into a create option, or is it just the fact that we need to get the traits? Alright. This is where things like cursor come in handy. Alright.
Write another script that will find all the unique traits and output into a JSON array. Extract unique traits, blah blah blah. Let's just call this traits dot j s. And then you can even go as far as, like, how what command to run this. No transform.
Blah blah blah. Maybe that didn't help much, but node traits dot j s. Was that output dot JSON or no? This is, this is gonna pull the oh, that's gonna grab my actual other one. What is this thing?
Transform. There we go. Traits dot j s, and then we'll do this as what? Oh, traits. Where are we at here?
I'm in the wrong directory. Output traits. Traits dot j s. FS is not defined. Man.
Just having fun with this all day here. Alright. Two snake cases not defined, of course. Should've just copied this entire file over. Alright.
So if we got the traits alright. So we'll do this the old fashioned way. Sunglasses, serious, smiling, great, short hair, eyeglasses, Bald. Black hair. Hat.
Blonde hair. How fast can you type, Bryant? There we go. Alright. How are we doing on time?
We got, like, thirty minutes left. We got feminine, lipstick. What else we got? Necklace. Neutral.
Red hair. Gray hair. And because this is the primary key, if I try to do one like sunglasses that we already have, it should throw this out. Yeah. Value has to be unique.
Okay. So I I think we've got them all. Did we get smiling? I don't know if we got that one or not. Smiling.
We did get smiling. Okay. Alright. Let's try to import this again now that we have all those existing traits. If not, like, we could just use the create, add new syntax, invalid foreign key.
Yep. Alright. Let's go back to our script that I wrote here just to get this data correct. Traits, we are going to add this in a we're gonna wrap this in this syntax. So create, update, delete.
And then we're gonna pull this. So this will basically give us this syntax, if I pull it up in the docs. Right? Traits. Not traits.
Create, update, delete. Is that gonna show? Basically, whenever you're creating items in here if we make this full screen, Relational data. So Directus allows you to create relationships or relational data through a specific collection. Sometimes it's better to use the detailed changes syntax.
So, basically, you say, okay. Here's the records we wanna create. Here's the ones we want to update. Here's the ones we want to delete. And that should populate everything that we need.
We're just gonna run this one again. Node transform. Output JSON. Alright. So this should create a record in the junction collection.
Let's try it again. Output dot JSON. Start import. Invalid foreign key. Don't tell me that, sir.
Do not tell me that. We need those traits. Start import. In the collection, Ravitar traits. Invalid foreign key for the field trait.
That is the foreign key. Did I goof that up? Ravitar traits. Trait, Ravitar. Create trait sunglasses.
Let's just shorten this up. We'll try it with a different file. Yeah. Can we get one of these to actually import? Import one dot JSON.
Still not sure what I'm doing wrong, but that's the beauty of doing this live. For trait value is required for the trait. There is a trait. Import one dot JSON. File prompt.
Oh, I'm inside the trait. Start import. Import one. Okay. So we got one to import.
I don't understand what we're doing here. Why isn't the full file working? Eyeglasses, brown hair. It should be working. Right.
Now we can see that works. Was I just in the wrong one again? Not paying attention? No. Is there one where trait is empty?
No. Feminine red. Where's our output traits again? Traits. Alright.
Let's just do this. We'll do a little sort. Sort lines ascending. Bald beard, black hair, blonde hair. They're missing brown hair.
Yeah. So if I was smart, I would have, figured out the way to make these traits actually auto populate. But, again, that's the beauty of doing these things live. Import one. Okay.
That works. So we'll just delete these guys out. Cool. Let's try the actual output file. We're still missing one, aren't we?
Bald, brown, black, earrings, eyeglasses, feminine, gray hair, hat, lipstick, masculine, long hair. Long hair. Attention to detail matters, Brian. Long hair, masculine mustache, necklace, neutral, red hair, serious, short hair, smiling sunglasses. Okay.
Now we have them all. We've just seriously burnt a lot of time on this, and that is gonna put us in a time crunch. But no stress. Right? So this should now take all of that data, import our avatars, make sure the files are linked up, and this may take a moment just because it is, like, digesting all those relationships as well.
What do we got left? Twenty three minutes. Where are we at? We've got a lot of rabbitars that we can manage. We can now manage our traits as well, which is nice.
How do we generate new rabbitars? Right? Cool. If I wanted to just update these a bit, I could go in and show a tiny image preview here just so we could see what that rabbitar actually looks like. And then I would probably go in here and update my interface to show, like, the trait name as well.
And we'll display related values. We'll show the trait name. So now I can see, like, the actual traits here. Smiling brown here. I don't have a name for those.
We probably not gonna get to that portion of it. I guess we could use AI to generate a list of names for these, and you could probably even pass it. Like, some of the ones like OpenAI, you could pass it the the actual image of this and have it give it a name. But here, I don't even really need the prompt. Right?
I just wanna see the individual traits. Cool. Neutral brown hair. There's that. And I can make this a little more cozy, or what I might wanna do is just add this to a card's layout.
Traits. Trait. We're under pressure trying to generate too many files, maybe. Bump bump bump. There we go.
Oh, that's a good one there. Yeah. So now I get to see these actual Ravatars, and you'd be able to navigate these through the file library as well. It's just nice to be able to see them through the lens of the the associated traits as well. Right?
So if I went here and I went to trait, it should be showing those. I don't know why it's not. But anyway, there we go. We want to be able to generate new rabbitars as well. Let's go through and create that step.
Right? So anytime a new rabbitar is generated, generate new rabbitars. Generate new rabbitar. Let's do this. Is there a new icon?
Perfect. You know, I love icons. Alright. So anytime we create a new Ravitar entry, after that's created, let's go in and call that OpenAPI a OpenAI API. I always get hung up on that.
So here's our collection. So anytime an item is created in the Ravitar collection, we're going to run this flow. And I could test that just by doing something like this. We go into Ravitar and create a new one. We're going to call this Doctor.
Phil the Ravitar. What traits is he going to have? Bald, gray hair, eyeglasses, Sirius. Cool. There's our traits.
Alright, we hit Save and Stay. Cool. And there's Doctor. Phil, right? So that should have actually triggered this flow to run.
And we can see that in the logs and it should pass us the actual data. So we can see here, here's the individual traits. Great. Cool. Now what?
Now we are going to generate an image. Alright. Generate image, and that is gonna be using the AI image generation. And now we're gonna need an open API key, platform.openai.com. Log in.
How are we doing on time? We got 19 left, man. We're cooking now. Let's get logged in. Alright.
Where are you? Dashboard. API keys. We're gonna create a new secret key. Direct to sleep week.
Okay. Yeah. We'll do that. This is what we call rabbitars. Create the secret key.
Copy. Let's throw this in here. That's the secret. Alright. Do I have these are part of the rules.
Right? Do I have the prompt that we use to actually generate these bad boys? That would be handy. That would save us a bit of time. Wouldn't it, Brian?
Where are you? Leap week. Leap week. Leap week. Leap week.
What is this? Leap week? Leap week. No. That's the actual template, isn't it?
Oh, boy. Alright. Directus. Where are you? Lots of projects in here.
Event OS. Virtual events, I think, is what this is. Server API. Is is this the one? Let's see.
There we go. Okay. So there's my prompt. Photorealistic head on headshot of a single rabbit set against a back black background with detailed fur and realistic texture, and then we're gonna pass it the attributes that we want. Let's give it a name, traits.
And we'll do standard quality square as the size. Alright. So now what I'm gonna do here is just add a little connector, and we could see, like, the data that we're getting back. I just wanna clean this up. We'll just copy this over here, and we'll make this half screen.
So I'm gonna do a little run script operation. Cleanup is what we'll call it. And we're gonna take the data coming from this. So we'll do here's the, let's just call it the payload. And that will be under the data key, we'll find trigger because it's coming from the trigger.
That will be the payload, and then we're gonna return traits. Right? So we want const traits equals payload dot create dot map, trait. And we want to return trait dot trait. Return trait.
We just wanna return that, don't we? Trait dot trait. Traits. Okay. The name will be payload dot name, if it exists.
And no. Actually, that one should exist. Payload dot name. Name. Payload dot name.
I need a comma and traits. And I could paste this in here just to verify that this is actual test dot j s. Is this actually properly formatted, or are we we're throwing an error there. What am I missing? Oh, we're missing a there we go.
No. Return. Okay. Concentrates. I think that should be proper now, except we don't need that.
We got the return in the wrong place. Okeydoke. I think this is gonna work. And, you know, always test first. So we'll just go in and create another avatar.
Be Jeezy. He is going to have, what, long hair. How we doing on time? Fifteen minutes left. Super masculine sunglasses.
Save. What do we get coming back? Are we seeing this the way we want it to be? Cannot read payload dot map. Payload dot create.
What was the actual payload? Traits dot create. Payload. Data dot trigger dot payload. That doesn't need to be asynchronous.
Data dot trigger dot payload data dot trigger. Was there not a payload? I could've swore there was. Yeah. Trigger dot payload.
Turn trait. That'll loop through these. We should have a trait dot trait. Create dot map. Create traits out.
Yep. There you go. Sometimes you miss a option there. Let's try it again. BG.
Sunglasses. Masculine. Long hair. I just have this up in a bun right now, by the way. Jiraiya new Ravitar.
Cool. Now we get the traits. Can we just return the actual list of trait? Treat dot treat dot treat dot treat. Okay.
Cool. Flows. We have new flows. There we go. Okay.
So this is what we're gonna pass to open AI API. Cool. And traits is gonna be cleanup dot traits. And the name, cleanup dot traits. Cool.
And then we will pass cleanup dot name. K. And then the next thing that we're gonna wanna do, we should get something back from this, but then we'll have to import a file as well. But let's test this out. We could try that doctor Phil one again.
That's great. Beard, gray hair, bald, serious. Woah. Save. And I could even open this up in a new tab if we wanted to do some fanciness here.
Just flows. Alright. We see this flow less than a minute ago. Okay. This has given us this is the actual URL.
Okay. So there's the Rabatar that was generated. There it is. Square standard. Here's the URL.
Right? So now we need to import this URL into Directus. Right? So for that, let's go to the docs. And let's look at the API reference.
So we're going to go to files accessing files. We don't want to access we want to create files. Importing a file. Alright, so using the REST API we can import a file. And what we're going to do here is basically just call this thing.
Import file. Cool. We will use the webhook request. This is what? A post request to ravatars dot directus dot app slash files slash import.
And we're gonna pass it two things. Right? We're gonna pass it a URL. URL is what? What's the URL?
What did I call that last step? Generate image. So we're gonna access that data through this key, and I I think it'll actually just be generate image because it looks like all we're getting back from them is a string. And then we're gonna pass an authorization header here. Or what I could do instead is just allow anybody the ability to upload a file here, which if we save that, I can go into our access policies, go to the public one, and allow anybody to create a file.
That's what I'm gonna do here. This is not recommended for production use. Obviously, you don't want anybody in the general public with the ability to upload files. Generate a new rabbitar. Cool.
And this should the last step of this one is going to be do we get the actual ID of the item? Right? There's our key. So that's gonna be trigger dot key. What we're gonna do is update this.
We're gonna update that rabbitar. Update rabbitar. From the collection there. We're going to do full access just to make sure we've got it. Then we're going to do this.
We'll do the trigger. Key. And then the payload, we're gonna have the file that we get back from that last operation. So file is gonna be import oh my gosh. Is it just called import?
It's just called import. Alright. So we'll do file. So that's the inside the Ravitar collection, that's where we're storing the relationship to the file. And that will be import dot data dot id.
I wanna say that's what it should be. Import.data.id. If it's not, it's not. Okeydoke. Alright.
So let's try this again. We're gonna do Bry Guy, Bry Ross. Cool. Bry Ross has red hair, smiling, eyeglasses, long hair, very masculine, and a beard. K.
We'll hit save and stay. And I think I had I had Directus pulling it up at at one point here, didn't I? Let's just go in. We'll check our flows. Less than a minute ago.
Update Ravitar. Invalid syntax for type UUID. Okay. So we got this back. Data.data.ID is what we need.
So we didn't quite get the updated one. Data dot data dot ID. Alright. But I should be able to see that Ravitar in there. Right?
Yeah. There we go. Alright. So let's try this one more time with six minutes left on the clock. What do we have here?
Test. Bry Ross. We'll just pick a bunch of these eyeglasses. Red hair. Cool.
Beard. Save and stay. And I'm gonna copy this link. We'll go over here. No.
Not that one. Got arced again. Test. Bry. There it is.
Right? So we can see here we created this fourteen seconds later. There we go. We have our AI Rabatar that is generated for this one. Bada bing badda boom.
We generated new rabbitars. Now we can generate those on the fly, which is great. And because this is a direct us flow, even if I created these via the API, like passing traits, it would call that OpenAI API for me. Do we have enough time? We got five minutes.
How can we generate a random avatar based on or how can we return a random avatar based on a seed? I I'm not even gonna attempt this one, to be honest with you, because, normally, I would wanna set this up on, like, a probably, like, a custom extension, instead of, like, a flow or something like that. But it it is doable. I wanna end on a high note. So just recapping.
Right? We have generated a directory full of AI Ravatars that we can then manage and query and do all sorts of things with. We can manage traits, and we can see all the Ravatars that are within those as well. You know, we might even clean this up a little bit. So I can see for the interface, I wanna show the Ravitar and I wanna show the file for that Ravitar.
So now if I take a look at these, right, we should be seeing, like, a little list of those Ravatars there. That's a particularly ugly one there. I'm not sure what happened with this one, but, there we go. That is generating an AI Gravatar directory. More goodness to come in the next episodes of 100 apps, one hundred hours.
Join me. We'll see you. You.