Cloudflare TV

💻 Dev Challenge: Random Rendering

Presented by Gretchen Scott, Luke Edwards
Originally aired on 

Developer Challenge #4 was to use the Unsplash API and render random images. Here is a walkthrough of how it can be done.

Join the Cloudflare Workers Discord channel!

Developer Week

Transcript (Beta)

Hello. We're nearing the end of Developer Week. It's been quite the journey. I'd like to say good morning, good afternoon, and good evening, depending on where you are.

I'm Gretchen, and Luke is here beside me, and we're going to talk through the most recent Developer Week challenge solution today.

But before that, I just wanted to quickly go through a couple of basic things.

If you've got any questions for us at all, email them through to livestudio at

They come through to us and we can answer them as we go.

It's day five of the challenges. We've had so many great things put out into the universe around Developer Week, all the product announcements and all the new things happening, and the developer challenges have run alongside helping to get people up to speed on using what's in the ecosystem.

So it's been great to see all the solutions and ideas and questions that have come through and to see our developer community on Discord work together with one another to get things up and running.

I think our first challenge, if you haven't done it, was just deploying your very first worker.

We called it Hello Worker and asked you to go off into the universe and do your first worker following a tutorial, which was cool.

The next one was pick a framework. So we wanted you to use pages and see how easy that was to get something deployed.

Yesterday, we went through building a Discord bot and rendering some photographs and that's one of my favorite ones along the little journey.

Today's one was about hitting an API.

We want some random rendering to happen because you need to be able to interact with APIs.

But alongside of this, we had some quite challenging challenges, even more challenging than people that were already experienced with the platform.

And so one of those projects that I had thought would run from Monday to Friday was to build out a portfolio project around, you were pretending you're a concert promoter's senior developer and you wanted to be able to show local concerts to people that visited your website.

And some of the solutions that have come through to that are unreal.

It's also really interesting to see what concepts are being held around the world at the moment.

It's a mix, I tell you. It's well worth going to the channel for that and Discord and having a look around at what people have built.

Because people totally blew us away with that one, someone finished it in 15 minutes, which I was completely gobsmacked.

But I think it just goes to demonstrate how easy it is to get things up and running with the Cloudflare platform.

I'm still trying to process that actually. If I'm honest, one of our community members came up with a SAS project, which is pretty tricky too.

So that's a great one.

I can't wait to see what comes out with that. There's a good, I don't know, it's an interesting one.

I wouldn't be able to do it right now. So I'm intrigued.

I'm also super excited for the weekend. So all of these challenges we wrote together as a team, but they build up and build up on one another.

And then when we get to the weekend, there's some really cool projects happening.

One of them gets you to kind of use Chrome triggers and we're hitting, we're doing HTML rewriting and all kinds of fun stuff and pulling it together.

So it really is about, well, we've tinkered with this, we've played with that, you gave that a go and the weekend bonus challenges, let's pull it all together and have something fabulous.

And then the super user, sorry, power user bonus round. It's honestly, it's a cool project, isn't it, Luke?

It is, yeah. I am a little lucky. So I got like the sneak peek of all of these.

And that one was definitely my favorite one to dive into.

It touches everything. Well, it does. Not everything. That's a bit overkill.

You're having to do kind of to -do listy stuff. You're having to integrate with, do I say?

You have to play with, I won't say. We have to wait till the morning.

And also uses Chrome triggers, which they have so many different uses, right?

So it's super exciting to see what that one does. And what we're also doing that I'm, I don't know, seriously is going to be cool is people whose challenges or solutions to those come out, we're going to sit together as a team and figure through who's, we think is amazing.

And we're going to get them on Cloudflare TV to talk through, you know, their planning journey, what the code was, where they got stuck, where they got excited, why they made the choices they did.

Can't wait for that. So that'll be near the end of next week. We stream that on TV.

So get your submissions in for that one when we finally announce what it is and can tell you what's happening.

Again, the solutions to the code we are putting up or what we walk through today, we're putting up on the Discord channel after the event.

It's an instant hop off TV, jump, put them in there, but we'll pop them up so you can have some references to what we were talking about during the segment.

And again, if you have any questions for us about what we're doing as we go, the live studio at is the place to send it.

And also we spend a lot of time talking about our Discord server and the community there.

If you haven't joined that, please do. It's the best place to get information.

And it's just a really cool group of people who care about coding and help each other out.

So if you Google Discord community Cloudflare Workers, you'll find us.

It's a great place to be. But today's challenge or yesterday's challenge actually that we're solving today was called random rendering.

And so we asked you to walk through a tutorial with Unsplash.

And it was quite a, I liked the tutorial, told you where to go, gave you some good instructions.

The Unsplash documentation is reasonably good.

The tutorial tells you that you'd walk through, asks you to render guitar images.

But we went, I don't want guitars. We want random.

We want to see whatever pops up. As we went through, it became a little bit clear that maybe we should have used some of the other parameters that Unsplash has, like maybe changing the size would be good because the images are pretty massive.

So we implemented that as we went, but didn't force anyone else to through the specs of the project.

But Luke, how did you get started with this one? What was your planning step?

Sure. So I thought I could just hit a standard endpoint, but I found out right away that you actually have to ask Unsplash for an access key.

So we had to create an access key as our step one.

And we're major dizzy right off the bat, just like yesterday.

So when you get inside Unsplash, you can just find this super easily, but there is a your apps section.

And here's our DevWeek challenge four, but creating an access application is just as simple as accepting some terms.

Cannot talk today.

There is a lot of terms there. There are. But basically, you have to use these respectfully.

And the main call out, which is also in a few places in the documentation, is you have to preserve the Unsplash URL itself.

I'll get back into this in the code itself, but you cannot pretend that the images are your own.

So it's a great description right there. But you create your application, takes you in, and then you need this access key.

So this is meant to be private.

It is calling it out here. We do not need the secret key in this case, but this value here will be added as a Wrangler secret in your application.

For me, I declare at the top.

Again, I'm using TypeScript. Because I know this will be a binding within my application, I'm just declaring that global thing.

This will be a string during my runtime.

And Wrangler takes care of that for me. But for the rest of the documentation, if we actually look at it, there's a whole lot here.

You know, getting started tells you how to create your account, how to register your application, and it tells you the tools they offer for you.

This hot linking section here is their big call out saying we require image URLs to be Unsplash URLs.

So let's be very respectful and respect that.

But, you know, through all of these things, you can get user photos, you can get the current user details, specific photos, random photos, you can Unsplash itself, as you would imagine, has its own search API because you can be searching for foxes and animals like our Discord for our Discord bot challenge, right?

Does it make you want to go back and use this on there?

It might. Actually, I did want to do that as part of our challenge yesterday.

And my first pass, I didn't see that there was actually the provider access, the provider value as part of the Discord embeds data layer.

But by the time I had gathered all of those image URLs, I didn't want to go back and re-choose images.

So I just kept what I had, because they were all Creative Commons licensed anyway.

That we could quite simply, now that you've done Flickr. Yes, definitely. So we're back at this get random photo section.

And so it tells us, you know, where the endpoint is.

They call out there, please respect our URLs once again. And we see some parameters.

But before we get into the actual parameters, we have to set up that request.

So if I look at the bottom here, you know, we'll have our standard fetch listener, events responding with some handler value.

So that comes in, we get the request itself.

And immediately, we want to parse it, right. So rec.url, this is the actual full string of the URL.

And because we're, because this is going to be an endpoint of our own, in this case, it will be unsplash

And because our endpoint is designed in a way that we don't actually want to care about the path values, we only care about the search parameters.

And that's solely because we saw this little hint at a parameter section down below.

So that'll come back in once again. I can hide this. So what we have to do is we have start recreating a new URL destination.

So that is this. This is, again, API.unsplash.

And here's that photos.random, which came directly from the documentation.

And we, let's hide this for right now. At this point, what we have to do is we send off that fetch request, right.

We are, when we send this request off to Unsplash, it's going to respond with a 200.

And it's going to respond with our rate limiting errors, or our rate limiting counts.

This is directly tied to our application token.

And some of the terms that we agreed to, right, is that you cannot use it too much, unless you upgrade to a 5000 requests an hour.

It's something like that.

I think it's probably 100 an hour, but I agree. It feels like a lot of photos.

I'm trying to think of use cases where you'd hit, you know, that many an hour.

Yeah, it's definitely very, it's very lenient, very generous, especially for a free application.

And you can have tons of them. Maybe it's 1000, because it's here in the example.

It was a big call out. I can't remember it off the top of my head.

But it's, it's definitely usable for this. So the documentation shows that when we send this get photos random, we are sent a 200, along with our rate limiting details, as well as, as well as this response data object.

And I do have a larger one for us, that we can sort of walk through.

It's exactly the same thing.

But we get the photo ID, a bunch of stats about it, its width, its height, some applications will make use of this, you know, for like an image tag, layout sizing, whatever you want to do.

But there's a lot of information here, as well as the user data.

So you can highlight the photographer who took the picture. That's cool.

Even their Instagram username and which camera model they used is in there. I didn't see the camera model.

Where was that? Keep going down. I had camera model, where I saw something.

Oh, yeah. Wow. Exposure time. This is amazing. Aruba. Very cool.

And the view count and download count. That's pretty cool. So it's a very, it's a very, you know, it's a popular API.

And for good reason, right? Like there's a lot of good data here.

But what we care about is, so we fetch this request, it had to be a get.

And then we pass in our client ID key. And I am sorry, but I forgot to actually call that out.

It's somewhere here.

Photo. Actually, I think it's here in the authorization. But basically, it's the point as to why we actually had to create that application, right?

So user authentication, basically, just give us your client ID. I can't find exactly where it goes.

But this is how it goes. It's directly that same value that we copied from earlier.

It just goes into the authorization, authorization header. And that's how we, that's how Unsplash is keeping track of our rate limiting data.

And that's really all it's there for.

That makes sense. So they just force you to count.

Yeah, they're forcing you to be honest about what you're actually doing. And when you are accessing, there was that secret key, which I think has to do with like, accessing your own photos or accessing other users photos.

And so that's where it comes.

That's where authorization for photo access comes into play to not relevant at all to this, because we're just using public photos and random photos.

Anyway, we send off this request, we just saw the headers and as well as a response to that, we get back all of what we care about is the URLs object, which is this, right?

So I have a preview thing here. So URL is an object and has a bunch of links, right?

It has raw, which is, as Gretchen mentioned earlier, we found out this is the raw image.

Like this will generally be, you know, 30 to 60 megabytes, at least, probably 100 megabytes of photo, we have a full size, regular size, small size thumbnail, but these are all different.

We can see they're all the same photo, this 16748 identifier, but they all have different query parameters as part of it, because that's just how Unsplash transforms our images.

But we don't have to care about it. The raw was huge, wasn't it?

I hadn't thought that through. And we went, oh. So for that, at that point, we have URLs, and then we're deciding which size to get.

Right. So originally, we had defaulted to using that raw image, but we didn't want to wait 45 seconds per image to download, or at least for my Internet connection.

And so we just have some sort of simple validation here, and we make it configurable for the user itself, for the user requesting our endpoint.

So in this case, I am offering this size query parameter.

Again, input is the incoming search parameters from our request. And so if there is a size parameter, and it is either regular, small, or thumb, we are disallowing the raw version, and we are saving that value as a key, and using that key to come directly from our URLs object.

So again, if it's regular, small, thumb, I can't remember if I said allow full or not, but anything other than raw, we make sure we finalize this URL's key, and we're using that to grab the image URL.

That becomes our image itself, and if we want, oops, if we want, we can just redirect it right away.

So if we look at that now, again, it's our unsplash.lukey.workers. It is a plain request, and we can see that, it doesn't update my URL bar, we can see that it redirects to a images.unsplash .com, some photo ID.

We have no control or no knowledge of what this value was going to be, it is just what Unsplash sent us.

If we do another one, right, we get a different image.

I hope everything that comes up is safe to show, but these are all.

It is random image rendering, so we're just trusting Unsplash on this one.

Okay, so now we come back to our customization part, right?

Did I lose that random? Here we go.

Okay, so the random photo request itself, it accepts parameters, right? So these are the query parameters that this endpoint can accept.

So it can be collections, I don't know any off the top of my head, we could find that.

It could be a specific user's photos, it could be some sort of search text, a query.

I'm just obviously seeing here now content filter, which perhaps we should have applied before we did a live screening of random images.

Oh yeah, well, we'll hope for the best.

I don't know what content safety is, which guarantees no content violating.

Okay, so low is the default, and so by default, there's nothing that's going to be violating the terms.

Perfect, we're safe here. So query orientation, which can be landscape, portrait, or squarish, and then a count thing, which we will see that gets removed just because count changes the response type, so we could easily just say no counting allowed.

Anyway, so I created this forward request, which again, takes the input, the incoming search parameters, and it's forwarding those parameters onto this URL that we were creating, right?

So we have get slash photos slash random, and this is still a URL instance, which means it is still mutable, we can still adjust it, we can say unsplash dot path name.

At this point, this is photos slash random, but we can set it to hello, right?

It would break in this example, because there is no API, this becomes slash hello, right?

This becomes a final URL output, which we don't want to do, but we do want to manipulate the search parameters, and these are the keys that we are looking for from the input.

So if we look at this forward helper, our faces are covering some of it for me, but this forward helper takes a source parameter of search parameters, a target parameter, as well as a bunch of names, loops through those names, sees whether or not the source has that value, and if it does, it just sets it directly.

So it's a very simple helper, and right off the bat, it allows us to do stuff like this.

I have a bunch of, oops, this way. So if I paste this in, right, this is all black, it's hard to see.

Let's do another one. So these are all categorized as landscape photos on unsplash's side.

So, you know, whatever's here.

They make it really simple, don't they, for you to get the size and shape you want?

Yeah, so if we change it to portrait, we can see it's now portrait.

Portrait. Oops, that is an error, because that's not correct. It doesn't exist.

Exactly. So important to call out, there is no validation on this, but there probably should be as a next step.

There's also a query here, so we can unsplash, and query equals, what was the tutorial?

Guitars? Yeah. That's not a guitar.

I don't see a guitar here. Again, this isn't up to us, but it's whatever. Query equals guitar.

It's not a guitar either.

Come on, unsplash. It's not a guitar. We had some music, at least.

Some of the classification on some of them, when I looked a couple of years ago, was a bit wonky.

There was one of a woman cutting a fish, like a salmon.

That was a chef scene. And the description was something like businessman at desk with cell phone.

It was like, no. When I was making this, I typed in pizza quite a bit, and I kept getting cotton candy and like ice cream.

So at least they had the food category in place.

But again, not really our responsibility here.

It's such a hard thing to get right, though, as well. If you were going to do this, I mean, it was quite a simple project.

You're hitting their endpoint, following their docs, and it just happened, right?

Like it was easy. Where else would you take this?

Or where do you think you could use something like this, either in a little kind of side project that you might do yourself, or in a production-ready corporate setting?

Sure. I mean, the easy thing here, I guess the final part I want to show is that Unsplash also exposes a bunch of image mix, imagics?

I don't know how to pronounce it. But the service that they use to actually render and manipulate these images, it takes its own bunch of parameters.

And so for me, this was a nice little exercise just to separate the query parameters.

There's nothing else all that interesting happening here. It's the exact same thing.

It's input source parameters, applying it to this image URL that we received after the size handling and accepted for values.

But beyond this, I would probably start saving.

I would stop relying on the random aspect and start saving images directly.

So if this were my service, I could finally find a pizza picture that I like with the correct query parameters that I like, whether or not it's landscape, portrait, squarish, some size, and save that as a as a named URL that I want to use again and again.

So that would bring in KV. And that would then mean that this on the initial stage, we would actually start caring about, right, like this would be here, and we can call this path name, path name.

And our first step could check, could use the path name to see if it actually exists in our KV name store, namespace.

And I am kind of afraid to do a live coding here right now. But where would you take it?

Yeah, so I mean, that would be the immediate step, just because I don't think of, I don't know of any applications I've ever built that rely on a random image being returned.

Right. So, you know, so I would want to have slash pizza slash guitar.

And then beyond that move, you know, because the size logic is our logic, like unsplash, this is the only customization, the only flare that we added to the entire endpoint.

I would move this to a path segment as well.

So it would be, you know, my endpoint slash thumb slash pizza, right, as opposed to slash pizza and or, yeah, slash pizza and size equals thumb, right?

It's just paths are a little bit nicer to look at and to remember, and that sort of thing.

And that could be small thumb regular, it can be all the same options.

It's just we're pulling this value out of a path rather than relying on the search parameters.

That makes so much sense. I do love with unsplash, you know, just that because it is real photographers uploading their images that the quality and variety of what they've got is just unreal.

I hope they stay as they are now.

Yeah, I mean, I've only I've known of unsplash for years now, and it just keeps getting bigger and better.

And I am not ashamed to admit that there would be a couple, an hour to every few months or something where I would just go through and look at pretty pictures, right?

Like, there's some really good pizza I'm hearing.

Well, depends if I'm hungry or not, right. But nice landscapes and whatnot.

So I guess we'll share this, we'll share this code on Discord. We really, really want you to hop on Discord.

Like if we haven't made that clear five times already, we'd love for everyone to join our Discord community.

And from a personal point of view, I'm so, so keen to see what people come up with for the bonus round challenges over the weekend.

They, I don't know, I'm geeking out a little bit too excited about what comes for them.

And I'm really actually wishing I could just tell you all what they look like right now.

But it's Gretchen's excitement is warranted because it is an actual application.

Like not an actual application, but it's something you could actually use beyond just developer week.

It's piecing a lot of things together and it's fun.

It is quite fun. And it's one of those projects, if you're ever moving around or looking for a job or want to showcase the things you can come up with and build, it's one of the projects you can definitely put in that category of, hey, I built a thing.

I built a really cool thing that has a use.

So in that regard, it's a really good thing to do. And we haven't had any questions, which is cool.

And you're kind of running out of time to ask.

We're going to move away from that one. But TV is taking a break for the weekend because the fabulous people that make this happen for us need some time.

And I think that's pretty valid.

So no live TV for the weekend. Next week, we'll be back showcasing some of these weekend projects with people from the community.

So that's going to be absolutely fabulous.

And we'll keep popping up solutions to the challenges in Discord.

I don't know why that was hard. So today's challenge is building out a repo hunt.

So instead of product hunt, we're asking you to build repo hunt and find some repos that use workers.

If you can pull that together, which is, I don't know, it's actually, now I look at it, it's tougher than I thought when we wrote it.

We'll see what comes from that. Tough is good. Tough is good. It's a challenging project.

We hope you all have a fabulous weekend and have loved coming through Developer Week and moving forward with that.

So take care, and we'll see you next week.


Thumbnail image for video "Developer Week"

Developer Week
All the building blocks you need to create & deploy full-stack applications on Cloudflare. Tune in all week for exciting new product announcements and more!
Watch more episodes