Optimizing Cloudinary Images in Markdown Files

Markdown is great for writing your next blog post, but including images in a web-friendly way is challenging. Thankfully, we can use information from Cloudinary’s APIs to modify our Markdown to display properly sized images!

In this DevJams episode, we sit down with Brad Garropy, Developer Experience Engineer at Atlassian. He walks us through his open source project that uses libraries like Remark and Rehype to add width and height to Cloudinary-delivered images in Markdown files, as well as demystifies the topic of Abstract Syntax Trees (ASTs) for your next development project.

Sam Brace: [00:00:00] Hey everybody. My name is Sam Brace, and I am the Director of Customer Education here at Cloudinary. And this is DevJams. This is where we talk with developers who are doing innovative, inspiring, or at least interesting things. And in many cases, since I do work with Cloudinary, as well as my cohost, who I’ll introduce shortly, works at Cloudinary, typically the developers we’re talking to in these episodes are using Cloudinary as well. But with that said, the types of projects can wide greatly in all of the different things that they are doing. So we wanna be able to bring these to you in this format. So as I mentioned, I do have a co-host for this program and that of course is Becky Peltz.

Becky is our curriculum program manager for developer education here at Cloudinary, and I love having her as the co-host in all these episodes. She brings [00:01:00] a wealth of experience and knowledge for all of these conversations. So Becky, I am so happy to have you here again for this one.

Becky Peltz: Hey, I’m glad to be here and I think this is particularly exciting day since we’re live streaming. We have done this in a more non streaming fashion in the past, and this is exciting and we have a fantastic guest with a lot of good knowledge here to pass on.

Sam Brace: Absolutely, and it’s an exciting time to talk to somebody like Brad who we’re gonna be getting to know a lot more about in this episode, because Brad has been doing lots of really interesting things, helping out developers with his own blog, contributing to podcasts, but also has a day job working at Atlassian as well.

But one of the things that we’re gonna be talking about with Brad really is to better understand a couple of big topics, which are tied to his project. It’s gonna be able to understand details about Markdown. It’s able to understand details about also something called [00:02:00] abstract syntax trees, which you’re gonna start to understand a little bit better.

You may have seen these mentioned in certain types of articles about also known as ASTs, but these are two big things that have been coming up in lots of conversations when it comes to web development, software development, and sometimes tied to images and videos, which is why we’re getting involved in the conversation.

But it’s something that I’m excited to talk to Brad about today.

Becky Peltz: Yeah, I’m looking forward to him explaining how we put together Rehype with for Cloudinary images that he solves an important problem there and I think he is gonna be able to explain a lot to us about how to go about working with ASTs to solve this type of problem.

Sam Brace: Absolutely. Now, before we do get to Brad, and I just wanna point out to everybody that is watching this overall episode that if you are so inclined, you wanna see previous DevJams episodes, understand the things that Becky, myself, and other Cloudinary team members have done around this DevJams initiative.

You can always go to Cloudinary dot [00:03:00] com slash podcasts. And you can see here that there are many different links to the podcast programs that we have, including our latest episode, which focused on the way that Daniel over at Legitimate was able to build a Web3 marketplace with Cloudinary and talks about the ways that Cloudinary works from a Web2 to Web3 standpoint.

So it’s a fascinating episode, but it is to say that after you get to hear from myself and Brad and Becky, if there’s more that you wanna be able to be a part of, know that you can always go to Cloudinary dot com slash podcasts. And as you can also see at the very bottom, all the links of where you may be consuming podcasts already.

That could include Spotify, Apple Podcasts, Google Podcasts, YouTube, and even our own Cloudinary Academy. So lots and lots of great information there, just in case you are so inclined after all of this.

Becky, any final thoughts before we bring Brad on?

Becky Peltz: No, I think we’re gonna get into a lot of interesting conversation and he [00:04:00] has done a lot of different types of work with the this area and so hopefully we can cover all of that and be enlightened here.

Sam Brace: Amazing. Let’s get to it. So Brad, welcome to the show.

Brad Garropy: Hey, thanks so much for having me on. This is awesome.

Sam Brace: Brad, we talked a little bit about you, we said some things. What do you agree with, what do you wanna share with about yourself at this point?

Brad Garropy: You guys are right. I do have my hands in a lot of different buckets here.

I have a lot of side projects and that’s something that I really like to do is work on coding outside of my normal day job. It gives me just like a lot more perspective on the wider industry and allows me to solve problems and learn new technologies on my own.

Sam Brace: And I think it’s definitely something that I think as someone that’s trying to grow in their career is great advice for them.

Just in general, like when I’m trying to learn about the education space, since that’s what I do for my day job. If I [00:05:00] just focused on what I was doing for Cloudinary, I’d probably feel very insular with all the things that are taking place. But trying to keep your hand on the pulse of what’s new, what’s cutting edge, if it, there’s certain things that your day job allows for, but there’s certain things that it definitely doesn’t.

So to keep expanding your scope it’s needed. So I think it’s great that you’re doing what you’re doing for the development community by putting your hands in lots of different pots and touching it and feeling it and understanding it because it is something that I think helps us to grow within our various careers.

Becky Peltz: Yeah. And we know from talking to you previously that you actually graduated with a degree in electrical engineering. So you, that’s a tough one. And but you got into coding. And can you tell us a little more about what you like about coding?

Brad Garropy: Yeah you’re right. Electrical engineering was actually very difficult.

But throughout my curriculum I specialized in like computer systems, so I actually learned how to like, build computers from scratch, like how to build logic gates [00:06:00] to make memory and then make, adders and dividers and things like that. But through the course of that curriculum, I had two programming classes.

They were both in Java, and there was just something so satisfying about programming. You’re like doing this kind of creative thing, writing code because you can organize it in ways that work with how you think and structure your code that’s personal to you. And then it’s also like really great because you get immediate feedback, you make a change, you run your program, you see the LED turn on, it was all hardware stuff at the time.

So that immediate feedback I loved a lot and that’s where coding really struck me. And I wound up just kept going down that path in my career.

Becky Peltz: Yeah, I I’ve always teased with people that are learning coding that if you’re in a search for truth, you’re definitely gonna find it in a computer because if you do something wrong, it’ll tell you right away. [00:07:00]

Brad Garropy: Absolutely. Yeah. And coding is better at telling you what’s going wrong than hardware. Cause stuff just, if it’s hardware, it just doesn’t work. If it’s coding it, you got an error message or something like that.

Becky Peltz: Yeah. That’s true. It’s great that you got into it and now you’ve dived into some of the hottest stuff going on as you moved into like static site generators and and your blog is written in the static site generator, which we’ll get into more.

So how did you make that transition into this area? There’s many areas of computing we, we hear about Web3 and lots of many different things. So what attracted you to this?

Brad Garropy: Yeah, I I was working at Dell writing like very low level code. I was writing c code, making firmware for their servers, and it’s basically just like how you power on power off, update, change settings in their servers.

And it was just, it was tough. It was in the weeds. You couldn’t talk to anybody [00:08:00] about what you were doing. You certainly couldn’t show them you can’t just bring them into some big hardware lab and be like, see I did that. So I just found interest in doing things that I could share and web development was really kicking off at that time.

There was like a transition into Angular around that time and I was just learning how to like, build things and share it, whether it’s with friends and family or other coworkers trying to find ways to apply it at work. And then I made a really big jump. I left Dell and I went to Adobe, and that was like where all the doors opened for me.

They are a web company. I was working on web products and I got to just play with all the latest and greatest stuff because I joined a brand new organization and it was like a field day for me. I loved every second .

Becky Peltz: Yeah I think of it like a candy store at Cloudinary sometimes. There’s just so many things [00:09:00] going on that to, to play around with.

Sam Brace: So, Brad. When, now that we’ve explained some of the details about how you got to where you are in web development, I’d love to know a little bit about this project that we are talking about with you today. Explain to me some of the details about it, and of course, if there’s certain terms that I don’t know I might ask the questions about that, but tell me a little bit about the project.

Brad Garropy: Yeah, maybe I’ll start with like why it came about, because I feel like just spouting off the name of the project might not make a lot of sense if we don’t have context on why I needed it. As y’all mentioned, I wrote my own website and I did that as a learning experience early on when I was, starting in web development.

And this website’s gone through many iterations over the years. But one thing that’s stayed true is that I always author my content in Markdown. I have a blog on the website and I write content in Markdown because I think it’s important to own [00:10:00] your own content instead of putting it on a CMS you check it into your GitHub repo or something like that.

And so it’s definitely a challenge getting this Markdown that you write, which is like a markup language, but it’s very readable’. Intended for articles or text. And it’s a challenge to get that Markdown presented on your website in exactly the way that you want, whether it to get it to look a certain way, render a certain way, or even optimize the things that are included in that Markdown.

So yeah, that’s like where this project was birthed. I was using images on my website in my blog, and I needed them to not cause layout shift when you render a page and I can show more detail, but initially when you convert Markdown to HTML, images have no attributes on them.

So it’s a raw image tag with a [00:11:00] source on it. And so that’s where the customization really comes.

Sam Brace: Yeah, break it down a little bit for me because like I, I’ve used Markdown in different capacities for a good portion of like Cloudinary’s time, all of the blog posts were written in Markdown, so it was something that if you wanted author a blog post, it helped to provide it in Markdown.

So that way it was just an easy copy and paste for the publication team. But I know that you said about converting Markdown to HTML. What, talk to me about why authoring makes sense from the Markdown perspective, maybe particularly for a developer audience?

Brad Garropy: Yeah, for sure. So at the end of the day, you’re gonna wanna present this content on a website.

Websites are built with HTML, but you don’t wanna write a blog post in HTML. Think about it like P tags and a tags and like manually doing all that stuff. No, you’d rather write it in something that’s much more friendly, much more geared towards prose or text content. So Markdown fills that gap.

It’s a [00:12:00] specification that is very easy to read, like it’s very human readable and you could write a blog post in it, but it also has support for some HTML basics like tables, links, images, headings, and so just by writing a couple hashtags you can get a heading out of it once that Markdown is then converted to HTML.

So it’s the perfect tool for kind of writing on the web. You may have seen it on, GitHub in their README’s, or a lot of CMSs support Markdown. It’s becoming a lot more popular today because it’s just a couple little syntax things and you’re off to the races.

Becky Peltz: I think also you can stay away from a CMS in a way you can, Markdown can be your CMS.

So if you don’t wanna invest the time and possibly money in getting a CMS or even a database to put all of your thoughts and data in, you can just put it Markdown. And then, as you said, you can check it into GitHub or wherever [00:13:00] you’re storing your stuff. It’s yours, you own it. There’s no need to create any kind of integration except for the type that you’re gonna talk about in a little bit.

But in general it’s easy to read for anybody if, GitHub actually shows Markdown rendered as HTML for you. So yeah, it’s a great, in fact, I’ve heard people say, why do we even have HTML? Why don’t we just go to Markdown? You can just save a lot of time. But yeah.

Brad Garropy: And it comes with a fringe benefit. When used in like a blog post kind of way on my website, I have a edit this post if somebody wants to make a correction or something. And it essentially just opens a pull request with their edits. So it’s like really cool. It can be more collaborative that way.

Becky Peltz: That is, that’s a really great idea.

Sam Brace: I, I’m blown away just by that alone. That’s a great idea. Yeah. Note taken. That’s something that I might wanna do for other things that we do. That’s [00:14:00] really… nugget right there. But one thing I don’t fully get about what you were saying is when you’re talking about rendering issues when it was attached to Markdown or essentially display issues with the Markdown, talk to me about how that can come into play with Markdown files.

Brad Garropy: Yeah. Out of the box Markdown doesn’t do anything. It’s just a specification. It’s just a, it’s just a file type. It’s a dot md file. So in order to turn it into something you can use like HTML, you’ve gotta use some different libraries. And there’s some really high level ones out there. One comes to mind called Marked. And Marked will just do one basic transform on a Markdown file to turn it into HTML, Markdown straight to HTML, but you can really peel back the layers of that onion and do a lot of different things with it. So Marked may be the easiest and highest level package, but you can actually [00:15:00] get into parsing Markdown, transforming Markdown, and even modifying the output of Markdown based on this whole ecosystem called Unified, where it’s a collection of packages to turn these different file types into abstract syntax trees, make modifications to them, convert them between different file types and then ultimately spit it out as HTML or whatever you choose.

Becky Peltz: Yeah, and I think we’ve been focusing on kind of the text aspect of Markdown, but we know too that we can put images in there, we can put lots of other types of media in there.

Maybe we could move into looking at, cuz I, you’ve mentioned that the first step is to move it into one of these trees. We could take a look at that because I think you have a visual that we could share.

Sam Brace: Yeah, absolutely. Let’s put your screen up and let’s take a look at what you got going on.

Becky Peltz: Yeah, I, and [00:16:00] when I saw this, I really thought about how this is so much like what a web developer working in the DOM is used to, where you’re used to a DOM tree and you’re gonna be able to go in, traverse the tree, find the element you wanna change and make that change. So I like thinking about that way, but could you explain what’s going on here, how this works?

Brad Garropy: Yeah. This is called AST explorer.net. AST stands for Abstract Syntax Tree. And this is just a really cool way to visualize what an abstract syntax tree is. On the left, you have Markdown. If you’ve never seen it before, it’s pretty easy to read, right? It’s just like sentences. And you’ll see little annotations here, like this is a link.

So this link, the text that’s rendered is Vercel serverless function. But the identifier for the link is Vercel functions. So if you go down here at the bottom, this is like the link that it [00:17:00] actually links to. So it’s still pretty readable as you’re scanning through it. But this is technically like a form of code.

But in this particular situation, or I guess, let’s see, to tell you more about what this is. This is just like a sentence or two, like a paragraph. And if you look on the right, this is the abstract syntax tree representation of Markdown. An abstract syntax tree, you can think about it like, like a JSON file pretty much.

And it breaks every individual little piece of this Markdown file into its own node. So for instance, in Markdown, some of the basic node types you can have is a paragraph. And so you’ll see what’s really cool about this explorer is as I highlight the different paragraphs, it shows you on the left hand side what it’s referring to.

So the first sentence of the [00:18:00] post relates to this paragraph here. It’s of type paragraph, and it has some children with a text, a link, different things like that, because later on in this paragraph, there’s a link right there. So yeah, there’s a chunk of text, then a link, then some more text.

And this is the basics of breaking Markdown down into something that you can edit, modify, traverse, search, all these operations that you could do on a data structure to actually change what this Markdown can eventually be turned into.

Becky Peltz: And so when you’ve gotten it over into this point where it is in a tree and we can see it as JSON, we’re actually in this intermediate state where you’re not in Markdown anymore.

You are more of a kind of, I don’t know, just something that is more universal or, [00:19:00] not tied to any final format.

Brad Garropy: Yeah, exactly. So you can imagine if you were gonna take a Markdown file and eventually turn it into HTML, what it does is it goes from Markdown to an abstract syntax tree. And then there’s another kind of library or function call you can make to take that abstract syntax tree and then write it out to HTML and there’s these kind of libraries for all sorts of file extensions. You can actually do this for code, JavaScript or TypeScript, and code can be broken down into abstract syntax trees. That’s actually how ESLint works to walk through your code and look for problems. It traverses these syntax trees and, runs rules on each of the nodes in there and makes sure your code’s formatted or, annotated properly.

Becky Peltz: Yeah. So truly the word is abstract. It puts you into a situation where you, I could create my own file format and [00:20:00] then I could translate any of these other formats into my format by accessing it through the tree.

Brad Garropy: Yep, exactly.

Sam Brace: And Becky, looking at this, I can see. Brad, I can also see as well, like on like lines 40 through a few others, like lines through 45.

You’ve got different type of calls to images, which of course are Cloudinary hosted and delivered. So to your point earlier about this, Becky, a lot of times when people are talking about Markdown, they might be thinking about just being text-based, but this is indicating that there is media, there’s assets that are associated with this outside of just general markup of text.

Becky Peltz: Yeah. It’s, I, and it provides a Markdown provides a way to show images in its own format. Markdown also allows you to put HTML in it. It will generally render [00:21:00] HTML, so you can do it using that. But it is really interesting to think about what your next step was in the in, in getting into the Cloudinary experience.

So how did you move from looking at your Markdown like this and becoming familiar with the tree to the project that you used Cloudinary for?

Brad Garropy: Yeah, so basically outta the box Markdown has some basic transformations. For instance, if you put in a single hashtag and then this is my heading that’s actually a heading node.

So like Markdown syntax says that one hashtag is a H1. It corresponds to an HTML H1 tag. Two hashtags is a second level heading, an H2. [00:22:00] And Markdown has all sorts of these little shortcuts to map what looks like plain text over to HTML. Now it does the same thing for images.

And I can make this a little bit simpler. Instead of using these references, which are maybe a little bit harder to understand, Markdown space syntax looks something like this. Exclamation point with some square brackets indicates that you are starting an image link. And so what’s in the square brackets is the alt text, and what’s in the curly braces is the actual link to the image.

So Markdown takes that funny syntax and turns it into an HTML image tag with a source attribute of this url. And nothing else. And that’s great. But if you’ve worked with images on the web anytime recently, you know that images have gotten like way more complex [00:23:00] and making your websites optimized especially when it comes to images, which are one of the huge factors in optimizing a website.

You need attributes on your images for a lot of different things. Think about lazy loading, aspect ratio, all sorts of different optimizations, like source sets and things like that. So Markdown drops the ball here. But the ecosystem around Markdown has a lot of tools for helping with that luckily.

Becky Peltz: Yeah. When I looked at your image there, I only see five properties exposed through Markdown. And so you’re saying that we need, we really have many more properties, more attributes that we wanna be able to supply. Yeah.

Brad Garropy: Exactly. Yeah. So this image essentially turns into this funny image syntax essentially turns into this right here, image source equals this string. [00:24:00] Okay. So we wanna be able to modify this Markdown transformation, the default Markdown transformation, and do more. And there’s an entire kind of ecosystem for turning files into ASTs, making modifications on those ASTs, and then spitting it back out as some other file type.

Becky Peltz: Yes. And I think this is the exciting for, I had not heard of this before. I’m, I look forward to hearing more here.

Brad Garropy: Yeah so my use case was essentially images were not being optimized very well on my website. As I was migrating away from the Next.js image component, I was left with just the raw Markdown output, which was pretty suboptimal.

So I went searching and I didn’t find any libraries that did the kind of thing I was looking for. At the end of the day, what I wanted to do was add width and height attributes [00:25:00] to my images so that they didn’t cause layout shift. And if you’re not familiar, there’s this thing called the Core Web Vitals, which are Google’s metrics of seeing how well your website performs. And one of these core web vitals is called cumulative layout shifts. And it basically means as your website is loading, how much jumping around does your content do as different things are loading in. Because HTML can call out to the network and bring in additional resources as it’s loading the DOM.

So in this case, I really wanted width and height on my images to prevent layout shift. And getting a good core web vital score is very important because Google will actually rank you higher in their search results, in their SEO if you have a high core web vital score. There’s a direct correlation there.

Sam Brace: And I [00:26:00] wanna ask you about this because like with layout shifting, because we focus on a few different things when we talked about it from the image side of things like largest… like content paint and making sure that you know what is the largest piece of content on your site. Making sure that’s optimized, cuz that’s typically gonna be an image or video in a lot of cases.

But the layout shift isn’t something that we’ve really talked too much about in these episodes. Tell us more about why you think Google cares about this in terms of the core web vitals.

Brad Garropy: Yeah, totally. I can show you an example, right? It’s actually very jarring if you have a website with a lot of layout shift.

Imagine you’re loading something in and you start reading the blog post, but then images keep popping in later because they’re big and they’re, more expensive to load and the paragraph you were trying to read all of a sudden just gets pushed all the way down off the screen. That’d be super frustrating.

So having these width and height attributes lets the browser know the image is gonna be this big, or at least have [00:27:00] this aspect ratio reserve that space and then continue rendering. So this is a a blog post that I have called Securing Web Hooks. And I have an image right here where I’m showing the environment variable configuration screen in Netlify.

I installed this url throttler extension, so that I’m like making Cloudinary requests slow so that we can see the images pop in. And I’ll go to my code and make sure I’ve got this… yeah. Turned off. So if I load this page, you’re gonna watch as this image jumps in a couple seconds and it’s gonna push all the content down.

Sam Brace: Oh, there we go.

Becky Peltz: Yeah.

Brad Garropy: So imagine if you’re a really fast reader and that can be jarring, right? Especially if you have a lot of images. Or what if your header or your [00:28:00] hero image was on top and just push the whole page down?

Becky Peltz: I just have to share that I worked with making dashboards with images and, they would just come, and this was about 10 years ago, these things would come in and push the other one away and the whole page would re-render.

And then another one would come in, because it’s an asynchronous environment, you’re, you have no control over that. It’s however the network brings it in. But controlling the size can make a huge difference. So…

Brad Garropy: Yeah you can add like preloading to images but you’re gonna look at a blank white screen for a whole lot longer.

There’s a lot of different strategies on not only when you load your images but how, and what size you load them. So now with my plugin enabled if you refresh the page, you’ll actually see that space is actually reserved and the image then just pops up into that space.

Becky Peltz: That’s a great demo that really shows the importance of what you’re talking about.

Sam Brace: [00:29:00] Absolutely. It does. And it also, frankly, under, I better now understand why Google even care about this as being a core web vital. Because to your point, if you’re making reading and accessing content on the web hard by constantly shifting things up and down, then that’s not a good user experience.

So it makes perfect sense what you’re showing there. And I, it makes sense why they would rank it so highly in that case and good on you to understand that because you don’t wanna have your core web vitals impacted. And so understanding that’s gonna make for a better user experience for people that are reading your stuff.

Becky Peltz: Yeah. And just to be clear, what you did different is you added the height and width attributes to the image. And that was enough for the browser to make a good decision about it?

Brad Garropy: Yeah, so based on the height and width, the browser can then calculate the aspect ratio. The image might actually be larger than what’s actually displayed, but with the height and width, it knows the size of that [00:30:00] box.

They’re rendering this column here that has a max width of, whatever, 800 pixels or something, and it says, oh, if this is an aspect ratio three by two you can multiply that by the size of your column or your container, and it’ll know exactly how much vertical space to hold for the image.

Becky Peltz: It’s like you’ve reserved a table at the restaurant and then you got that space no matter what.

Sam Brace: Yeah, I was just about to use an analogy myself. I love that, that you did that but I can also see this being really helpful because as we know, the web is responsive now, and this makes sure, to your point about aspect ratio, if you’re keeping that same aspect ratio, this means if someone’s looking at this on their iPhone in portrait mode all the way to a beautiful desktop display, it’s gonna ensure that image still has the same level of placeholder regardless of what the pixel width and height that’s gonna be because it’s allowing for that set amount of space based on the viewport.

Brad Garropy: Yeah, and it was just recently that width [00:31:00] and height became important again. Images can now calculate aspect ratio through width and height. Prior to that, you had to specify aspect ratio, which is even one of the newer image properties as well. So all of this stuff is just coming to the forefront once again, because browsers are getting smarter with what they can do with these images.

Sam Brace: So how did you pull this off? I saw of course you, you did the AST example, so you were adding width and height and details in there, but it, how do we, how did you start going and doing this more turnkey with what you’re doing with your blog presence?

Brad Garropy: So yeah this really was enabled by the Unified ecosystem, which helps transform things to and from ASTs and then make modifications to those ASTs.

I think that was the question you were asking, right?

Sam Brace: Yeah, exactly. Exactly. So how did you end up doing that with the Unified system?

Brad Garropy: [00:32:00] Yeah. So Unified is complex. You can find it at Unifiedjs.com, but it’s very complex and this is something I feel like I wanna make a course on in the future because there’s just not enough information out there to figure all this stuff out.

But how I did it, let me open up the source code so I have a reference here.

So one of the first things that you can do in this Unified ecosystem is you can write your own plugin and you can use this plugin at any point in the chain of transforms that you’re applying to your Markdown. So for instance first you have to parse that down into an AST, and then you can apply multiple transforms at the AST level, and then you can change that AST over into a different kind of ast, like an HTML ast.

And now this gives [00:33:00] you HTML properties you can work with. And so that’s precisely where I started to inject the things that I cared about into the HTML. So you can either modify it like the Markdown content itself or swap it over to the HTML version, and then start working with like HTML nodes and attributes and things like that.

So in order…

Becky Peltz: …way to do that, right? You, we know, we, I could see in your, for example, line 11, rehype Cloudinary image size. So Rehype is a tool that you’ve incorporated to help.

Brad Garropy: Yeah, let me pop over here. This is probably a better a better high level overview. So this is the function that actually transforms my Markdown on my blog.

And the very first thing you do is you call into Unified and it says, okay, start my Unified chain. What’s the first thing you wanna do? You want to use Remark, which is a parser for Markdown to turn that into an AST. [00:34:00] And then you can see I’m like applying a bunch of transformations to that AST.

I’m using GitHub flavored Markdown. Unwrapping images, removing the paragraph tags around them. I’m changing the way these inline links work a little bit. I’m doing very fancy embeds for Twitter and Twitch and YouTube, and these are all just modifications to that Markdown AST. But then there’s a very pivotal moment here where I call Remark Rehype, and that’s a plugin that takes a Markdown AST and converts it into an HTML AST.

And these functions are all chained after each other. So like you’re, it’s just returning essentially the AST each time. And so now you have a HTML AST. And this is where I wanted to actually change the image tag to add width and height. And so I injected my own [00:35:00] plugin, my own Unified plugin to do exactly this.

And so this is how you hook into the whole process. And I’ll show you what that looks like.

So the name of the thing I made is called Rehype Cloudinary Image Size. It’s a plugin specifically for HTML ASTs to reach out to Cloudinary, grab some information about the image and then add that into image tags as width and height attributes. So you have to like actually create this this traversal of your AST.

And in this case we’re, walking around the AST looking for image nodes that are Cloudinary images. So you stop at every anchor link or rather every image tag in your AST. [00:36:00] Check the source attribute and make sure that has like res dot Cloudinary dot com and that way you know it’s a Cloudinary image and you can then go get more information about that image.

Once you have identified that, what I do is I run this little function called get image dimensions, which is an API call out to Cloudinary and then add those dimensions onto your image properties as width and height. And you do that for every image you find in your AST and then move on with the rest of the Unified chain and eventually convert it to actual HTML.

Becky Peltz: That is really cool…

Sam Brace: Maybe I missed it, and it hopefully you’re like, oh Sam, you need to pay better attention. But how is it getting those image properties? I understand it’s calling Cloudinary at this point, but what are the image properties it’s grabbing? Is it grabbing the original width and height or is it grabbing an optimized version of it? What is it grabbing there?

Brad Garropy: Yeah, so this [00:37:00] is where this get image dimensions function I wrote comes into play. And this is just leveraging the power of the Cloudinary API because it’s really good. I will say I use the Cloudinary API for like automatically optimizing my images’ format and quality.

So it doesn’t matter what I uploaded the Cloudinary, I can get a WebP on my website or I can retrieve the image at 80% quality where you don’t see terrible degradation or anything. But the same API can also get you like metadata about those images. And so I essentially just look at the source attribute and splice in this API endpoint that Cloudinary has called fl_get_info.

And it returns this really cool JSON object of all sorts of metadata about the image, including the width and the height.

Sam Brace: I love the fact that you’re using this and once again it [00:38:00] emphasizes the power of JSON in another way where it’s like the fact that you can get all of this additional metadata, get all this additional detail from something that’s being delivered by this, you can, it shows how you can use that information really well.

Becky Peltz: Just to clarify a little too there, cuz it’s pretty cool what you did here. You took the original URL and you added to the path you added slash fl_get_info, which is one of our transformations. And that allowed you to get back this JSON that you could then pull properties out of.

Brad Garropy: Yeah, exactly. Yeah, because you need the reference to the image and then you need to splice in the path and it’s nested after like your account name in the url.

So it, you kinda have to find that and then put it after that.

Becky Peltz: Yeah. Yeah. So you had to learn how our URLs are composed of domain, cloud name, transformation…

Brad Garropy: exactly.

Becky Peltz: Upload. [00:39:00] Yeah. And once you master that, then you’re able to figure out how to stick a little transformation into the path and do more with it.

Brad Garropy: Yeah. Now I will say one thing that, that would be really convenient here is if, maybe suggestion for Cloudinary, if y’all had an fl_get_info endpoint, that after that you could put a full like URL there.

Becky Peltz: I’ll share one little tidbit there that might get you there. We have what’s called a list type of delivery.

Like normal delivery is gonna be like uploaded, authenticated, various types of access control. But if you have list and you have tagged your assets, you can, what’ll happen if you call for the name tag, whatever you named your tag, you know like Brad, is you tagged your assets with Brad dot JSON with the list type, you [00:40:00] will get back a JSON you know, you’ll get back, it’ll be like you’re calling and getting, you’re getting a massive amount of information about each of your assets that are tagged with that.

Brad Garropy: And that’s for all tagged assets, not just a single asset?

Becky Peltz: It’s it, you have to have tagged with that, Brad. So if you tagged all your assets with Brad and you ask for Brad dot JSON, you get ’em all, there may be a limit, like if you have thousands, maybe there is a limit there. But in general, it’s a way to get back JSON data without having to use any kind of API secret or API key because it’s all public.

You’re basically considering back public information about your assets.

Brad Garropy: You’re making my gears turn because this kind of happens at runtime a little bit like when these are generated and I wonder if there’s maybe like a way to pre compile this image data so that we don’t have to make as many API calls.

This API call happens once per [00:41:00] image, which is one of the things I really had to optimize. I didn’t want to traverse the tree. Make one API call. Wait on it. Yeah. Find another node. Make one API call. Wait on it. What I did was traverse the tree, found every image, collected all those URLs, made all the calls at once.

They all came back altogether and then made the transforms. Yeah, but this is good cuz you could technically recompile everything, have a JSON file and just reference it. That’s nice.

Becky Peltz: Yeah. Yeah. That would work. I’m curious about ASTs that, with the DOM you have the query selector that’ll let you say, go get me all the image elements on my page.

Have they got anything like that so that you can, like just instead of having to walk through the whole tree, you can just grab certain elements?

Brad Garropy: That’s absolutely an awesome question. There are some helper functions that do stuff like this. So you’ll see that I’m using packages called [00:42:00] Hast, which stands for HTML ast, or Hast Util is Element.

And which is just to check on is the particular node I’m on an image element or a paragraph element? There is, I believe one called hast query selector or something like that where it can more directly access these nodes. But typically the way you do these trees is you walk them, you do walk ’em.

Yeah. And so it gets really complex in there because you can’t modify the tree that you’re walking. If you add a node underneath the one that you’re currently on, you could make a recursive loop because you’re adding a new node, continuing to traverse it, finds it, maybe makes a transformation.

A lot of what you have to do is save off your modifications for later and then apply them at the end or something like that. So that was something I shot myself in the foot with a couple times doing this because I [00:43:00] accidentally made infinite loops by modifying the tree that I was walking.

Becky Peltz: Oh, wow. Yeah, no, walking through trees is, that’s an advanced course in computer science, so yeah, it’s not for everybody, but you’ve got a really good example of how to do it here. So I think this could be…

Brad Garropy: One of those things where you learn just enough to make it work and then say, okay I get it.

Sam Brace: Brad, this might be a silly question, but I gotta ask you cuz I, I’m not sure if I fully understand it, but, so obviously I can see here that everything that you have, like the various files you’re showing Markdown dot ts, ts stands for TypeScript.

Is all of this stuff possible only because you’re using TypeScript or is it something where the techniques you could be shown, could they be done in other ways?

Brad Garropy: Yeah, a hundred percent. All of these libraries are JavaScript libraries. I choose to use TypeScript because I love the auto completion.

I love how it keeps me in my lane, gives me hints on what these APIs [00:44:00] do. And I just, I feel like it’s just becoming the gold standard for web development now. But at the end of the day, JavaScript is just a super set of, or sorry, TypeScript is a super set of JavaScript, so all of this is available in JavaScript.

Sam Brace: Okay. No, that makes perfect sense. And yeah, it I, everything I’m seeing here is just JavaScript in general, but I just wanna make sure that was clear cuz it’s where you I can see people that are maybe new to some of these concepts being like, oh, this JavaScript is not TypeScript, but JavaScript is TypeScript and I wanna make sure that it was clear.

Brad Garropy: Yeah, for sure.

Sam Brace: So now that we’ve seen these different processes that are taking place, one thing that I also wanted to ask you about, cuz I’ve seen it in a few of the examples you’ve shown, was this f_auto and q_auto. That’s coming from Cloudinary, of course, Cloudinary, we’re calling this auto format auto quality, and it’s dealing with making sure that images are compressed to a [00:45:00] certain value, making sure that it’s delivered in the most optimal format based on the browser.

Talk to me about more about why you decided to use this and how maybe you’re applying it to your images.

Brad Garropy: Yeah, so going down this path of image optimization, I’m using Next.js, but I’m trying to migrate off of it, but it’s like a process because you have to pull yourself out of their APIs one at a time.

So the first one that I got away from was the Next image component in React, which did a lot of this stuff for you. But I wanted to just write code that kind of works everywhere and be able to take it with me instead of being so bought into a specific framework. So when I lost image optimization, I was like, oh man, it’s gonna hurt my web vitals.

Maybe my SEO will be worse. So Cloudinary was like one of the first things I looked at because one, the free tier is ridiculously good, and two, they offer all of these transformations that are so easy to apply with the [00:46:00] URL of your image. And I was constantly writing in Markdown, so I just needed a way to access these images via a url.

I was, I didn’t wanna store them in my GitHub repo. It was getting too big for that. So I offload it to Cloudinary. And one of the things that, that Cloudinary does offer is image optimization. With this particular URL path, you can add in these this comma separated list of keywords that affect how your image is brought back to you.

And you could do like a lot of really cool things here. But the basics in my opinion are your format. Like essentially what file type this is. Is it a jpeg, is it a PNG, is it a svg, is it a WebP? If you use f_auto, Cloudinary will figure out the best format for the browser or device that you’re on and deliver that.

So I could have uploaded a jpeg, Cloudinary will serve a WebP if that works [00:47:00] best for your browser. And then the second thing that I have here is q_auto, which affects the quality of the image. If you’re serving it at, a hundred percent quality, you could probably get away with a little bit less, to be honest, and nobody would know the difference.

And I think just to test this out, what if I did, I think it’s q_10. Yeah, that looks much worse. I don’t know if you can tell, I don’t know if you could tell through the thing, but auto looks just as good as q_100 at the end of the day, but it’s a much smaller file size. Like you, you’re not gonna be able to tell the difference between a 100 percent quality and q_auto and it’s gonna save you bytes or kilobytes over the wire, meaning your website’s faster, higher SEO, better core web vitals, all that stuff.

Becky Peltz: I’ve gotta congratulate you on… you did a great job of explaining q_auto. I mean it, I think we should encapsulate this in it. [00:48:00] Very easy to understand.

Sam Brace: And I just verified it. I pulled it up on my screen as well and checked your profile page on your blog and yep, you’re absolutely right. Take the jpeg, it converted to WebP because I was using Chrome for my browser.

And so it, it makes perfect sense what you’re describing here. And one, once again, kudos for you to understand optimization to that level. But one thing that I would, I’m curious about is how are you applying f_auto and q_auto to your images? Are you baking that in through some form of automation?

Is it a manual add? How is this taking place?

Brad Garropy: This is something that I need to improve. I finished this image transition not too long ago, and right now what I’m doing is literally just using the Cloudinary URLs in my Markdown sources with f_auto q_auto in them. Going back to like my actual blog source code, you’ll see down here this Cloudinary image has that in there.

And I, that’s [00:49:00] actually something I was looking for is I don’t really wanna write another like a Remark or, yeah, this would be a Remark plugin to add these in there. I feel like there’s gotta be some setting in Cloudinary that says, just serve all my images like this by defaults all the time. So what do you say? Do y’all have that kind of feature?

Becky Peltz: We I think that feature, yes, in a sense we have a feature. But for developers, I think what we like to do is we have a SDK for JavaScript that allows you to add that kind of on the fly, or especially if you’re in Next, they can have it pre-processed, through the s… there’s or if you’re using Remix something, if you’re using an sdr… ssr, you can have that done ahead of time.

But yeah, so the SDK, I think is the easiest way to do that [00:50:00] automatically. And you could, you could use a JavaScript SDK. There’s React and if you’re doing React you could also have a microservice with Node that just did that, so you could just have that be your optimizer as you’re… and generally I would say you would be doing that during your building of your pages rather than real time.

Yeah. And I will throw out here that one of our DevRel, Colby Fayock, has written a plugin for the Netlify. So if you’re deploying to Netlify, he uses what’s called a fetch type, which is letting it uses Cloudinary to proxy your image. So say your image could be sitting in your own assets folder on your website.

He’ll go out, his code will go out, grab it and f_auto, q_auto it, and get it into our into your [00:51:00] cloud or product environment. But it’s, it will leave the source of truth as your list of assets. So if you change that, it could get updated cache. But yeah. There are a couple of ways I think developers are doing this in that way, in and on, but I could bet you could come up with an automated way that would be even cooler than that.

So I don’t wanna tell you.

Brad Garropy: Yeah. I’m telling you it’s… Markdown. While it’s very great it’s, you’re not like in a runtime environment where you just have access to these URLs and can, and transform them and stuff on the fly. This is a very pre-compiled type thing where you’re working with raw source, trying to transform that.

Yeah. I gotta go back to the drawing board on some of this stuff. See if I can make it better. For sure.

Becky Peltz: Yeah, some of those functions that you see in the Next framework where they are grabbing your Markdown and doing some processing during the build cycle. [00:52:00] Those are those are great places to, to do that.

Sam Brace: So looking at this again and we’ve also alluded to some of this because we’ve talked about what our next steps for this type of project or what’s next steps for your blog presence, but what else are you cookin’ up? What other things are you doing when it comes to your blog, the delivery of maybe images, maybe not? But what’s on the roadmap for Brad?

Brad Garropy: Yeah, so I’m, like I mentioned, I had this effort to move my blog off of, I’ll show you what it looks like. Migrating my blog from Next.js over to Remix and in the process, trying to just take a lot of code that was very Next.js specific, like their image component and pull that out into kind of framework agnostic packages or code that lives in my repository because this website switches frameworks once or twice a year. And I just want that process to be easy, [00:53:00] essentially everywhere I go. So if I have one function that transforms my Markdown and grabs my Cloudinary images and stuff, then I can drop that in any framework anywhere and put it in the compile step and it’ll be just fine.

So it just helps me explore new technologies and makes me feel like I’m not like buying into one framework or one hosting provider or anything like that. So in this transition, I’ve had to do a lot of work. I had to get rid of the Next image component. I’m moving all of my CSS over to Tailwind because that just works a lot better in the Remix model.

And then at the end of the day, I actually have to make the migration over to Remix. So it’s a large effort, but it’s something I like doing cuz I always view this website as hopefully, the best thing that I can produce showing like where my skills are at today because it’s kinda like my landing page on the internet.[00:54:00]

Becky Peltz: All right. That’s a great idea to think of your blog that way is that you’re continually having it reflect what you’re interested in. The technology that you use to build it is the stuff that you’re working on. That’s a great way to do it.

Sam Brace: One question I have for you that you just mentioned, Tailwind.

Talk to me a little bit about that, because I see this constantly coming up in developer blog posts. Evangelists are talking about Tailwind in different places. We have not covered this topic at all when it comes to DevJams. Tell me just basically in your own words, what is Tailwind? Why does it matter? You mentioned it in the vein of CSS. Anything, details like that could be really helpful.

Brad Garropy: Yeah, Tailwind is a collection of CSS utility classes. So what that means is there’s a like a color blue class or a color red class, or a color green class or a margin [00:55:00] left two class.

And they’ve got like hundreds of classes and you might think that’s overwhelming. And when you first pick up Tailwind, it is, and all of these classes are just applied to your HTML elements. So if you wanna style something with 10 different styles, you’re putting like 10 different class names after that element.

And the first thing that people say is, Tailwind is ugly, but , you don’t understand the benefit. They think the authoring experience is ugly, but they haven’t thought through of why this matters, why it’s different than something like CSS modules or using even vanilla CSS or, using some other like Bootstrap or something.

So in those other solutions, the size of your CSS grows over time because CSS cascades, you’re afraid to remove things. So you style something new and you’re like I guess I just have to make a new class or selector and add styles there. [00:56:00] And so what happens is your style sheet just keeps growing.

And it can grow infinitely. Like even if you wrote your styles very well. Your website gets larger and you keep adding more css and that will grow indefinitely. Yeah. As you add more pages. Tailwind is cool because it has a set number of utility classes and that never changes. And those utility classes essentially enable everything in css.

So your CSS file stays the same size no matter how big your website gets. What’s even cooler is that all the classes you don’t use, they strip out. So your CSS file is exactly as big as you need it with a maximum size guarantee. And what’s even better is that CSS file is generated and it’s super cache-able.

So like you’ve got one declaration file, it’s cache-able all over your website, so anytime you go grab it, it’s very, very fast.

Becky Peltz: Yeah. I have to say too that it’s CSS is [00:57:00] hard. Anybody that’s worked with it. Yeah. The fact that the order of the elements in your CSS file has a big effect on what, how they’re gonna get interpreted is a hard thing to teach people.

And I worked on a project once where a guy looked at our CSS and he said, oh, I think this would be better if I alphabetized it. I was just like, terrible mess. I was like no. That’s not what it’s all about. So yeah, it’s a hard thing to understand CSS and how so if someone gives you CSS that’s all nicely formatted and guaranteed, and like you said, small, cache-able, all that, it makes a huge difference.

Brad Garropy: Yeah. And that’s the performance benefit of it. I actually haven’t talked about the the authoring benefits. They have a vs code plugin with IntelliSense that’s so good. It’s like TypeScript for css and it like has inline previews of all the colors and [00:58:00] descriptions of every property. It’s amazing.

So like it actually has a better experience than writing vanilla css.

Becky Peltz: That’s cool. Yeah.

Sam Brace: It’s really cool. And I’m glad you went into that detail because we actually got some comments in the… from the people that are watching this asking about CSS with this particular project. So I think this was very enlightening to be able to dive in and tie that into what we’ve been able to cover with all the things that we’ve talked about so far.

So thanks for that. Absolutely. And so it does seem if people are wanting to stay up to speed with what you’re up to… main… going to your main website or your blog is the best place to do so, but I also know you’re probably active on a few different social media areas. Is there any particular place where people can get the latest and greatest that Brad’s working on?

Brad Garropy: I’m all over the place. I do a lot of stuff but I’m very active on Twitter. That’s how I like, find out all about web development. I, hang out with all my friends there and stuff like that. So that’s [00:59:00] twitter.com/bradgaroppy. Actually, if you’re seeing my video, I’ve got @bradgaroppy.

That’s my handle everywhere. So I’m on Twitter. I have a YouTube channel where I make web development videos. I even talked about converting my website over to Next.js when that happened. And you can find me on GitHub @bradgarropy, as well as Twitch. I stream coding every now and then over there on my Twitch channel.

Sam Brace: Yeah, as we can see from your amazing mic and camera set up, hopefully you’re on that.

So that makes perfect sense to me too. But this is amazing, Brad, and obviously this is, in my opinion, this is probably just one step of a multi-part journey that is taking place with the blog redevelopment, reconstruction, working with images in these different ways.

So hopefully this isn’t the last time we talk, so if you have anything else that you’re working on, especially when it comes to the Cloudinary side of things, reach out and we’re happy to have you come back on any time. [01:00:00]

Brad Garropy: That’s awesome. Thank you. Absolutely.

Sam Brace: Thank you. Let’s say goodbye to Brad real quick.

Thanks again, bud. And we’re gonna go ahead, quickly sum this up. Becky, after talking to Brad, what do you feel your biggest takeaway was?

Becky Peltz: I just love the descriptions of why these things are done. Like understanding the web core vitals aspect of this. It’s such a simple thing to be able to have those width height attributes, but they’re not available in Markdown.

And so to come up with a way to, to make them available makes a huge difference. And the demo on that was really good. And just getting the overall understanding of this AST and how powerful it is. And he’s able to just spin this up in a JavaScript file, even TypeScript, but it’s basically JavaScript.

So really great to hear all that. And just a really well rounded look at where a web developer might be in this [01:01:00] time and space. Working through problems that we all are encountering with browsers and such.

Sam Brace: Absolutely, and it’s something that I’ve been hearing coming up a lot from many different people that work at Cloudinary is there’s conversations taking place about ways that people can be working with images better with Markdown files.

And I think basically Brad just demystifyed that entire thing. So if someone’s saying, how do I work with Markdown and images in general, but also Cloudinary images, then we just showed you an amazing example of that. And I think that’s something we’re being able to understand the processes, as you said, being able to understand the connection between this and abstract syntax trees, ASTs, it now is now coming to fruition and hopefully we start seeing more people using the work that Brad did developing the plugin or the work that he did in his GitHub repo, applying that to their own [01:02:00] projects for future uses.

Becky Peltz: Yeah. And I love that he gave so many good plugs to Cloudinary because we didn’t ask him to do that. Nope. But he really did seem to be able to embrace what’s going on there and just start working with it right away.

Sam Brace: Absolutely. Absolutely.

And I do wanna emphasize that if people enjoyed this episode, once again, make sure to follow everything that Brad is doing and then sim… similarly make sure that you are following everything that we are doing here with the DevJams program. Of course, when this episode is available on demand, you will be able to get access to that just by simply going into Cloudinary dot com slash podcasts.

And also, as mentioned earlier, if you are interested in seeing any of the past episodes, they are all there, including in all the places that you are likely consuming podcast content such as Spotify, Apple Podcasts, Google Podcasts, YouTube, and even in our own training academy that we have for Cloudinary, also known as the Cloudinary Academy.[01:03:00]

So make sure that if you’re so interested in DevJams and what we’re talking with, because we’ve profiled amazing developers, including people like Brad. So this is definitely not the first. This won’t be the last, and we hope that you guys are enjoying this overall experience. Becky, any final words before we let our audience go for the day?

Becky Peltz: Oh, I’m just gonna go out and try Remix now.

Sam Brace: I agree. I’ve definitely been inspired to dive into a few things that Brad showed in this episode. So as we say regularly, this inspires us at Cloudinary just being able to see all the things that you guys are up to. So thank you again, and we hope to see you all at future episodes and future streams of DevJams.

Take care everybody. We’ll see you soon.[01:04:00]