CodePen will host your assets, like images, data models, libraries, whatever. It’s quite useful! They are easy to browse, easy to copy URLs or code snippets of usage, served with the right headers from a fast global CDN, and heck, we’ll even help optimize them. It’s easy to amass a lof of them, as we allow you upload many at a time.

But while we had Bulk Upload, as it were, we didn’t offer any other “bulk” actions, until now. Stephen and I talk about how we added more bulk actions for assets, making them all the easier to manage. Shout out to our user with many thousands of assets which helped provide the motivation to get this out.

Time Jumps

  • 00:15 Topic introduction
  • 00:49 Side journeys that break through
  • 04:02 What is a bulk action?
  • 06:47 List view or grid view
  • 09:27 How many things need bulk actions?
  • 11:58 Sponsor: Memberful
  • 13:48 UI changes
  • 16:56 Individual files vs Pen API

Sponsor: Memberful

Memberful is a best-in-class membership software used by the web’s biggest creators. If you’re building a membership website for a client, Memberful handles the hard stuff so you can complete your builds quickly and your clients can focus on creating content while earning revenue with ease. It seamlessly integrates with popular tools like WordPress, Mailchimp, and Discord, so they can reach and monetize their existing audience. Memberful maintains GraphQL API, webhooks, and OAuth Single Sign on to make integration even easier.

Help your client monetize their passion. Get started for free at


[Radio channel adjustment]

Announcer: Today, on CodePen Radio.

Chris Coyier: Hey, everybody. CodePen Radio 382. I'm going to tell you we're going to talk about something called bulk actions, specifically for assets on CodePen, assets being a pro feature that you can upload files to CodePen and we'll host them for you and give you URLs and all kinds of other fancy features. It's a pretty cool pro feature on CodePen. We just improved it a little bit more. Stephen Shaw did some of the bulk of the work on that, I would say, so I have him here on the show to talk about that. What's up, Stephen?

Stephen Shaw: Hey, everyone.

Chris: Yeah, bulk actions. The internal backstory is kind of funny. We are so disciplined. We're so good. We're on this huge project, and we're like [grunting], "We've got to do this huge project. No side journeys. We'll never get anything done if we're constantly on side journeys."

Then once in a while one will break through, and we'll be like, "Yeah, but this one is so cool that we have to. We've got to just do it."

I think it was kind of fueled by we're doing a ton of API work at the moment, and the idea behind something like bulk actions is that, to be done properly, it needs some APIs in place to do it that we didn't have. But I think they were like, "Pfft, yeah, but you know we do APIs all day. Just add one more API. That ain't nothin'."

Stephen: [Laughter]

Chris: "We'll do that in two seconds." You know? So, I don't know. I can't explain exactly why this one hit, but it did.

That was in conjunction with a user request, wasn't it? They were like, "I have two zillion assets, and I'd like to delete 1.8 zillion of them." You know?


Stephen: Yeah, so assets are kind of interesting. We've got most of the work for assets happening on the client side, so like the API. It doesn't even really have pagination in a really strong way. For the most part, we're loading that assets data. Not really indexing but sorting all that data client side and all that.

Chris: Hmm.

Stephen: Just at the time that API was built, that made the most sense, so we kind of went with that. Reworking that entire API was not, definitely not, in the cards. But we had this user write in, one of our more extreme end-of-the-spectrum users of assets, that was way past the limit of just what we could load on the client. There was so much data to be passing around, and working with, in memory.

Chris: Right.

Stephen: They said most of them aren't even really needed, so that got us thinking about implementing some bulk actions, which we'd done a little bit with (in our admin interface) last year.

Chris: Hmm. Internationally, yeah.

Stephen: We really haven't done anything else bulk actions, but we did implement that because we needed it, so we had some precedence there for how we could implement that.

Chris: Right. Right because we were like, "Oh, we could just help this one user." We'll delete a bunch of them for you or something. Or maybe we could do a middleman thing where even though you can't visit all these assets quite the way that you want to, maybe there's a URL parameter we could give you that would fix it.

We ended up being like, "Ah, let's just do it right." You know? Unfortunately, we've grown up and now we only do things right. It's weird.

Stephen: [Laughter] It's a new policy we're trying out.

Chris: [Laughter] Yeah.

Stephen: We'll see how it goes.


Chris: What is a bulk action, though? If you've listened this far in the podcast, you might be like, "Uh, are you going to tell me what it is?"

Stephen: Basically any kind of action that you might want to do on multiple items. For assets in particular, the things that make most sense as bulk actions are deleting and downloading. That's what we implemented.

Particularly for this user, they just needed to delete a bunch of assets. They knew all these junk assets that they needed to get rid of, and they only wanted to save a few. So, made the interface work in a good way for that.

Basically you can select a few assets. You could search for assets and select those. You can select all that are currently on the page, and then you can delete or download those.

Chris: Yeah, I'm sure people can imagine an interface like that where it has--

At some point, if there's enough checkboxes vertically on a page, user interfaces tend to have a check all or uncheck all kind of thing. Or you could check 3 of the 12 or one of the 12 or whatever. But it does mean that you need some kind of selection interface. For assets, that didn't exist. That was part of the reason of hesitation on some stuff like this.

When you add a new feature, it's not just like, "I need a new API." I already talked about the fact that we needed that, so that has to exist. But you have to think about the UI. You have to think about the UX for it, and that has to make sense. If it's -- [loud exhale]

It's tricky because there's already a lot of user interface packed into a small area and assets to begin with.

Stephen: Yeah.

Chris: The fact that you were able to land on something that just didn't overdo it made me extra excited about the feature. You could probably, if your back was against the wall, design a dozen different ways to handle a multi-select in a list.

Stephen: Yeah.

Chris: You know?


Stephen: With this feature, there really was just so much about it that really fell into place and made it possible to knock out.

Chris: Mm-hmm.

Stephen: I think, overall, dev time, including the API work and UI and testing and all that, it was less than a day to kind of get this out, which was unusual, I'd say.

Chris: [Laughter] Yeah.

Stephen: For me at least.

Chris: There's a list. Assets are--

An interesting aspect of it is they're always in list view. If you browse CodePen a lot, we tend to offer things in two views: grid view and list view. Grid view is just a more visual way, like if you're browsing Pens in list view. You can see a screenshot or iFrame of what the Pen is. Pretty cool, right? That's a useful way to do it. But list view is the one that has a little more - I don't know - on-the-ground functionality.

For example, if you're viewing a collection, you can view a collection in grid view. A very nice way to browse a collection.

But if you're down and dirty and want to do something like rearrange the items in a collection, which is a feature we released a while back, you have to flip over to list view. Then you can do that. Now you're just dragging in kind of a two-dimensional, vertical way, and it just feels natural and normal to be rearranging there.

Assets only come in list view - for whatever reason. It's just a UI thing that we decided on. That's nice because it means that we can just take this one view and make sure that it has some kind of bulk-selectable way to do it.

The way Shaw envisions, I think, right away we ended up just going with it. As you hover over it in list view, a checkbox appears. It doesn't push anything around.

Essentially, what it does is it puts the checkbox over top of the icon, which the icon is not super vital to the experience anyway. It's more of just a quick kind of glance at what the thing is, and you can kind of still see the color of the icon anyway around it.

Stephen: Yeah.

Chris: So, you don't lose all the context. It was a really nice solution because you need the dang little checkbox. You need an on/off, a selected or not selected interface for bulk actions.

Stephen: Yeah.

Chris: If I want to select seven things on a page, or all of them, there needs some visual way to indicate that, and you were able to pull it off with a very light UI treatment.


Stephen: Yeah, and it's subtle, but it still allows it to be easily accessible. Once it's checked, it stays there so that it's really obvious which ones are actually being used. Yeah, that was a helpful little UI decision.

The icons are good, but it's mainly just about telling the different file types apart (if this is an image versus a JavaScript file or whatever).

Chris: Yeah. Yep. So, imagine you're looking at your recent assets, and there are about five of them you want to delete. In the past, you'd have to go hover over it, open up the little three-dot actions menu, hover over delete, click delete. A modal comes up that confirms the action and then delete it.

It's got to have the modal because it's not undoable. You know if you delete that thing, we wipe it off the face of the earth, so modal is necessary.

If you had to delete seven of them, that's -- how many steps is it? One, two, three steps for at least seven is 21 little things you have to do with your little mouse. Kind of a lot, so bulk--

Stephen: Yeah. Very, very slow.

Chris: Yeah, very slow, and kind of like annoying too. Nobody loves a piece of software that makes you do that. [Laughter]

Stephen: [Laughter]

Chris: We're shooting for you to love CodePen, so we kind of want to be there for you. Behind the scenes, we already know that bulk actions is a big deal. If we weren't so busy working on other stuff, I would think bulk actions for everything, all around CodePen, would be pretty high on our list of things to jump on and get into the interface.

We're not dragging our feet on it. It's not that we don't want to deliver that for you as soon as we can. It's just a small team. Got to make choices about what we work on. We have bigger choices we're trying to do. But it does feel cool to ship it.


Stephen: Well, there's a lot more to consider with--

Chris: Yeah.

Stephen: There's a lot more to consider with bulk actions of, like, pins and collections and all those kinds of things versus assets where it's a lot more scoped down and limited in the amount of UI.

Chris: Right. Just the two things, download and delete, right? I mean theoretically, it could be like, "I have these five JPEGs, and I want to copy the CSV of all their URLs or something."

Stephen: [Laughter]

Chris: It would be a little bit more convoluted after that because we do offer resizing and stuff like that, but it's done on a temporary basis. It doesn't alter the original. I guess duplicate could maybe be one of them.

Stephen: Yeah, you can make a duplicate of it, but yeah, it's not as much of like a bulk action.

Chris: But who selects ten things and then wants a duplicate of all of them? I'm not going to say nobody wants that, but it's certainly less. Nobody has ever asked for it. Let's put it that way.


[Guitar music starts]

Chris: This episode of CodePen Radio is brought to you in part by Memberful, which is an awesome piece of software to help you build membership-driven businesses.

Say you're a developer and your goal - just to make this extra developer-y, let's say what you're going to do is build a website in order to sell an online course to other developers. We're a developer ourselves, and we're building things for other developers.

How am I going to do that? How would I, Chris Coyier, build that? I'd probably spin up a WordPress site just because I happen to know WordPress, but that's a smaller consideration than knowing that Memberful has a really powerful integration through a WordPress plugin.

What that means is I can build the site any way I want, have a wonderful homepage, have sales pages, have a blog, have a podcast that I know I can protect through Memberful for members only, have the video course page laid out with an ability to mark courses as done. All that stuff, I know that I could build that in WordPress. But then I know, through Memberful, that I know that people will be able to sign up. I know I'll be able to make annual plans and monthly plans and one-time plans and team plans and all this stuff that I need to do.

I know that I'll be able to lock down access to different parts of the site and put upsells there depending on whether people are members or not. I know I'll be able to have different levels, so I can say you get access to this if you're at this level and these additional things if you're at this level. I know that I'll have all the tools I need as a developer to build the site that I want to build and know that Memberful will take care of so much of this stuff, emailing people, charging cards, and repeating charging cards, and that server-side protection of my content and my pages for these paid plans.

That's how I would do it. I would just use Memberful and use WordPress and know that it really would be a nice experience as a developer. Thanks for the support.

[Guitar music ends]


Chris: All right, so that's cool. Yeah, and the easiness is cool. So, let's say you select 5 of them or 30 of them or whatever. Then all of a sudden, the user interface gives you those options that weren't there before. You'll see a little change in the UI, and it'll say, "Do you want to clear the range? Do you want to select more things? Do you want to download them? Do you want to delete them?"

If you hit delete, you have to go through the modal again to confirm that. Then all three of them are going to whisk themselves away, so there's no surprise here. Of course, that's how it works. That's the whole point. This isn't fancy. This doesn't even require documentation.

Stephen: [Laughter]

Chris: I'm not going to write a docs page for this. Who cares? I think you understand how it works. Click the button. You delete the things. You know?

Stephen: Yeah. One of the keys to the UI that I wanted to make sure worked well was making sure the selected interface didn't get in the way of just regular assets kind of work just viewing the list of files, editing them, or copying the URL of them, searching for them, sorting them, all that kind of stuff.

But as soon as you select one or hit the select all kind of button--

Chris: Yep.

Stephen: --then the interface becomes focused on that kind of bulk action. From that point, you can't page around. You can't filter and sort. You've got something selected. Choose to do something with it or clear that selection.

Chris: Or unselect them. Yep.

Stephen: Yeah, and it makes perfect sense, really. How weird would it be to select some assets and then paginate? Then you wouldn't even be able to see what you had selected anymore.

Stephen: Yeah.

Chris: Yeah, I think this is a very clear path for this, and it certainly solved that user's needs and, hopefully, the rest of you all out there too. I know it's not every single day that people need to perform bulk actions upon their assets on CodePen, but I'm telling you the day you need to, you're going to be glad this is there.


Stephen: Well, everybody likes making backups, so you know the bulk download feature is really helpful to make sure you've got a copy of all your assets.

Chris: Yeah, that's true. You want them all. You've got to do them 30 at a time because you can't select more than that at the moment, but that's going to save you a lot of time, really.

The API mentioned was just one on our side that says, "Please perform the delete action on this array of items, not just one item," which is what we had before. It wasn't even a new API. It was just an altering of the delete API to always take an array. It's either an array of one or an array of many. And rock and roll. That part was pretty easy.

The download is actually not an API, though, interestingly. Some download things are very much (and somewhat complicated) APIs on CodePen. When you delete a Pen, no small amount of API action is happening to make that happen. But these are just individual files, and I think we just kind of kick it right from the browser, don't we?

Stephen: Yeah.

Chris: It doesn't get a Lambda or anything.

Stephen: It's completely client-side triggering, like a download link, essentially, that gets it downloading. So, the bulk actions for that, in an ideal world, you'd probably zip it up and download all of that. But because all of this is happening on the client side, it just downloads the individual files all at once.

Chris: Ah, right. That would be like a minor improvement we could make is to bundle them for you and offer them as a zip or some other compressed format. Yeah, that's not what happens. If you select 30 assets and hit download, it's going to download 30 files right to your desktop.

Does it throw up a little warning thing in some browsers? I bet it does. Like, "Are you sure?" [Laughter]


Stephen: Uh, yeah. Like Chrome, if you haven't already given permission to download multiple files, it's like, "Hey, are you sure?" But even if you were downloading the assets individually, as soon as you click that for more than two, Chrome starts to flag that.

Chris: Yeah. Good job, Chrome, because that would be annoying in browsers. It's almost amazing to me that it lets you do it at all. Isn't it really--? I think it was surprisingly janky how it works, right? Don't you wank an A link in the DOM with the download attribute on it and then fake-click it? [Laughter] That's basically how it works.

Stephen: Yeah. Yeah, surprisingly, as long as it's from a user-initiated action, I think that's cool. If you did it on page load, I don't know that it would work.

Chris: Right. That's funny, though. That's there. There's not some really clean browser or DOM API that's like, "Download the file at this URL to the user."

Stephen: No.

Chris: It's like, "No. No. You have to make an anchor link with a download attribute and the href of it is the file that you want to download." [Laughter] That's not right. Is that right?

Maybe there is some file system API to do it or something that would allow you to pick the download location. I don't know. I kind of doubt it.

I like how dumb this is. [Laughter] Bonk. Download.

Stephen: Yeah. Browsers don't want to give the access to the file system at all to websites, but there are some APIs for interacting with it in a very limited way. It has to be very user-approved.

Chris: Yeah, totally. I think it shows a big ol' banner. You know? Which I think is different than downloading a file, right?

Stephen: Mm-hmm.

Chris: You might get a little -- on your third file, you might get an "Are you sure?" kind of action. But it's not the same as geolocation or whatever that you have to really clearly agree to or whatever. But it makes me think of that, or whatever, how that works, and you have to approve file system access and all that. I think skeeved out on CodePen if we asked for that.

Stephen: Yeah.

Chris: Despite us being the code editor kind of thing, be like, "What are you asking for? Hmm..."

And it's usually the other way around. It's like, "I need files on your computer to look at," not "I'm trying to put files back on your computer."

Stephen: Yeah, it's more about importing, usually. But there is kind of a bidirectional approach that you can take there.


Chris: Yeah, well, if you want to try this out, this is one of our more popular pro features because, as you build a Pen, having your own custom images or your own custom JSON data or your 3D models or custom fonts or whatever. There are lots of reasons, of course, to have access to flat files as you're building things on the Web. CodePen has a pretty robust asset manager for helping you do that.

But it's pro only, so upgrade to Pro on CodePen. You'll have access to the asset manager. You get to it from your user menu right in the upper right of CodePen. Use it until your heart is content (if you're pro). Unfortunately, you will not be able to experience the glory of bulk actions unless you're pro.

Stephen: If you've ever dealt with a cores issue across origin request - whatever - issue, just use assets. Go Pro.

Chris: [Laughter]

Stephen: Upload your file to CodePen assets, and you will not have any trouble with that. We've gone through great, great lengths and many, many support tickets to ensure that you have as smooth an experience as possible with assets and cores.

Chris: Yeah, that's so funny.

Stephen: Trying to inject a texture into a 3D model, you'll run into so many issues unless you have things properly set up, so we've taken those steps for you.

Chris: Yeah. Yeah. Uh-huh. I remember all this. You had to make sure the bucket policy is correct, and then we send it through Cloudflare, and Cloudflare has to honor the heading or almost like triple-check that the cores header is there to make darn sure it's there. You know?

I remember that; cores everywhere. Isn't that a website that existed for a while there?

Stephen: Oh, yeah. It used to be. Yeah, I think it's shut down. [Laughter]

Chris: Yeah, I mean there was a proxy, but I think it was almost like an open letter, like, "Please, for the love of the Internet, serve your assets with an allow anywhere access - or whatever. I kind of get why people don't and why it exists on the Web, but not your CodePen assets, baby. Those are ready to be used.

Stephen: By design.

Chris: Yeah, by design, indeed. All right, everybody. Thanks, Stephen, for talking about the feature. This is our mouth blog post for our feature announcement.

Bulk actions now available for assets. Pro only.

Stephen: [Laughter] We're no longer a podcast. We're a mouth blog post.

Chris: [Laughter] All right. See you again.

Stephen: Bye.

[Radio channel adjustment]