Syncing Local Folders to Cloudinary for Automated Cloud Storage

Cloudinary⁠ regularly hosts internal hackathons! These allow employees to stretch the boundaries of what’s possible with our products. ⁠Hadar Bejerano⁠, the head of the Solutions Engineering team, created one of the winning projects. With ⁠CloudyDesktop⁠, users can sync a local folder to Cloudinary for automated uploads!

Find out how he developed this desktop application in this DevJams episode. You’ll learn more about ways to use ⁠Cloudinary’s CLI⁠ in your projects. Hadar also shows how to use some of the project’s tools and packages – ⁠Electron⁠, Keytar and ⁠Chokidar⁠.

If you’re trying to find a way to automate your team’s uploading processes, this is an episode you won’t want to miss!

Sam Brace: [00:00:00] Welcome to DevJams this is where we talk with developers who are doing exciting, interesting, innovative, inspiring things with images and videos inside of their development projects. And because this is a program developed by those at Cloudinary, it probably means that they’re using Cloudinary in some form or fashion with that image and video management or delivery.

My name is Sam Brace and I am the Senior Director of Customer Education and Community here at Cloudinary. And I am so excited for you to be part of this episode where we are bringing on Hadar, who is leading our overall solutions engineering team here at Cloudinary. And he’s been here at least as long as I’ve been here.

And I’ve been here for quite a while now, but he’s developed an amazing project called Cloudy Desktop . And what this is doing is allowing for you to [00:01:00] sync a local folder that you have on your desktop, whatever you have for your local storage. And then link that to a folder in your Cloudinary account. Now, that’s pretty simple, but it’s also something that is going to show you a lot of different ways to start thinking about the extensibility of the APIs and Cloudinary’s own command line interface.

So that way you can start developing your own projects for ease of management, uploading, and organization of your overall files. Joining me for this episode when we are going to be talking with our friend Hadar, as she is for many episodes, is Jen Brissman, who is a Technical Curriculum Engineer here at Cloudinary and a member of the Customer Education team.

So Jen, it is great to have you here for this episode.

Jen Brissman: Hey, happy to be here.

Sam Brace: So why are you excited to talk to Hadar today?

Jen Brissman: A few reasons, but the main one being I’m really excited that this project was developed at a hackathon. And it’s really cool when something developed for not a [00:02:00] necessary reason becomes this awesome tool that people can get such a great use of, so I’m hoping this inspires some people today.

Sam Brace: Absolutely. And it’s a really good teaser into some of the things that we are going to be talking about here today. And of course, Cloudinary’s hackathon culture is something that we haven’t dived in too deeply into in any DevJams episode, but I am very excited for me and you to do that today with Hadar.

So great point about this overall episode, and hopefully it percolated some ideas for people to be thinking about as we get into that portion of the episode. Before we do bring on Mr. Hadar, I do have to of course, point out that everything that we will be discussing in Hadar’s project is going to be located at That is where our projects, some of them have been inspired by hackathons, that have happened within the company. They’re going to be found here. So this is a way for you to extend the overall capabilities of what Cloudinary has done, where we’ve had developers like Hadar that have done that.

They’ve really outreached and found ways for Cloudinary to do very [00:03:00] interesting things, including ways to have, as you can see, in painting interface to remove certain objects from overall content, ways to easily inspect your media. Even some of the things that we are really pushing when it comes to our Media Library and Chrome extensions for that.

Lots of things that happen to be here. So definitely take the chance to review for all details about Hadar’s project, including others that have been part of our Cloudinary Labs effort. Also inside of the Cloudinary Labs section, you’ll see that all of the code for Hadar’s project, Cloudy Desktop happens to be there and that’s in an open repository on GitHub.

So make sure if you want to download it, check it out, extend it, do what you want to do to be able to play with it and get it to work for your needs and use cases or just general inspiration. It happens to all be there for you to fork, download, clone, whatever your heart desires . On top of all of this, Make sure you are checking out all the podcast episodes, not just this one, [00:04:00] on Of course, we also happen to be probably wherever you like to listen or watch podcasts at, whether that happens to be Spotify or Apple Podcasts, Google Podcasts, YouTube, even our own training Cloudinary Academy. And keep these conversations going, of course, in our Cloudinary community.

That’s going to be And that includes the forums that happen to be there, as well as an associated Discord server, for overall conversations that happen in these episodes, or anything that happens to do with Cloudinary, or general tech that you’re working on in your stack. Lots of good things to remember.

With that said, I think we’ve done enough promotion for the stuff that we do, Jen. Let’s bring out our friend Hadar here. Hadar, welcome to the program.

Hadar Bejerano: Hello, how are you?

Sam Brace: Good, we’re good. We’re so excited to be talking with you today. It’s not just a case where we’ve developed this amazing project, but you do a lot of really innovative things.

Being the person [00:05:00] that oversees the engineering efforts of the Solution Engineering team, and the operations that are associated to that, you’re definitely tied to a lot of really cool, “let’s get people excited about what they’re possibly able to do with images and videos” when you’re talking to lots of different types of audiences, whether those are customers, prospects…

We do a lot of that work, Hadar. So tell us a little bit about that. What does that mean for someone that leads the SE efforts at overall Cloudinary?

Hadar Bejerano: Yeah, so first of all, great to be in this podcast. Amazing team to join. As you said, I’ve been in Cloudinary for more than seven years now. And I lead the solution engineering team, which is the pre sales team in Cloudinary.

Now, Cloudinary is both a platform that is used by developers and, but it’s also a very visual platform, right? You upload a lot of visual media into it, images and videos. And us, as the solution [00:06:00] engineers, as the pre sales of the platform, what we do is talk to this audience that wants to use Cloudinary and show how they can use Cloudinary on their projects.

And because it’s such a visual platform, it’s really easy just to share your screen, show how it can be done. And there are a lot of APIs that allows easy integration, but also a lot of really amazing features that just look so great. So anytime you get the chance to demo the platform, people are wowed and it’s really a great experience to be part of that.

Sam Brace: Absolutely. And I completely agree with everything that you said. Highly visual, highly engaging platform that we have here, of course. And hopefully this doesn’t turn into too much of an advertisement for ourselves. But it is where some of the things that led to the creation of this Cloudy Desktop project that we’re going to be talking about today.

Was there any experiences you had from being in SE, leading the SE team that said to you, this is [00:07:00] something that more customers could use or it could be used in projects?

Hadar Bejerano: Yeah. So I think because SEs talk to prospects all the time, we get a first hand look into what interests our potential customers and users of the platform, what’s top of mind for them, what is an important requirement for them.

And being a cloud based platform means that you have this ongoing requirement of taking the work that you’re doing locally, on your computer and sync it up to the cloud. In the same way that we hear other many requirements as well, right? So there’s so many use cases that Cloudinary supports.

But this one looked really interesting to me because it included that technical challenge of also doing something locally and natively on your desktop. While most of the [00:08:00] work that is done in Cloudinary is web oriented and web based. So trying to merge these two worlds together with having this real requirement from the field was the reason to try and take this project on.

Sam Brace: Wonderful. Wonderful. And so looking at something like Cloudy Desktop from a very high level, just break this down for us. What exactly are we doing here? Because as I mentioned, there’s going to be syncing between a local folder and a Cloudinary folder.

So it means that you’re taking something from local storage to cloud storage, if I understand this correctly. And then also that means that you’re using aspects of our Command Line Interface (CLI) to do so. So what gaps am I missing here in this like basic rundown of what this is?

Hadar Bejerano: So I think the main point is that you don’t want to do this manually, right?

You have all these files and it’s up to you now to make sure that you have the latest updated in your Cloudinary [00:09:00] account, which is on the cloud. And it would be great just to, to have that automated. Because Cloudinary is really open to integrations and APIs, there are so many times that the Cloudinary is the backend behind automation of many mundane processes that you do around media management.

In this case, it’s just syncing the work that you do up into Cloudinary. That’s one of the challenges. The other challenge is also the fact that, in this case the project is actually multi platform. So the code that we will review can be compiled to both a Mac and a Windows application. So you actually get an XF file and you actually get an app file and you run it from a local and from the same code So that another challenge as well so you can support all [00:10:00] different users that use different types of desktops .

Sam Brace: I think that’s one thing that’s actually very unique about this episode that we’re going to be doing here today is that I don’t think we’ve ever had any project that we talked about, it had to have a Mac version and a Windows version.

So that alone is very intriguing in itself to be able to talk about here today, Hadar.

So this is very cool. And to your point, I can see why it would make things a lot easier if there was just regularly syncing between something locally so that way, whatever is in your Cloudinary storage, it is what happens to be within that folder.

So you can just keep adding to it as needed and just automatically brings everything through so that you have it for cloud storage. And then of course all the amazing transformations that Cloudinary provides with optimization, aesthetics, etc. So this is wonderful. Is there any big points that we’re missing here before we start diving into the project?

Hadar Bejerano: No – before going into the technicalities of this, just pointing what you mentioned earlier, but all of this started from a hackathon, right? [00:11:00] Cloudinary… Because it has this API based platform and it serves developers, it’s part of all sorts of hackathons, right? So we have customers running their own hackathons where they use one of the groups might use Cloudinary to try and do a cool project of their own.

We have global audiences that can be part of Cloudinary Hackathons that sometimes are open to everyone that uses Cloudinary and can join one of our Hackathons. And the third type, which is a very common one, are Hackathons that we run inside the company. Once or twice a year, and everyone is really excited, you get to team up with people that you don’t know from other departments. You can, people list ideas before the day, of things that they want to work on and you can just join the team and also this project started with a team. I was not alone working on this. Once people like the idea and join you, then [00:12:00] you have that 24 hours where you need to run and code everything in a day or sometimes less.

So that’s pretty cool as well and a great, I think, culture in Cloudinary to keep doing this and get an interesting project out of it.

Jen Brissman: So how much of the project that we’ll be talking about today was built within that 24 hours, and then how much was, you know, kind of trickled over time to improve it?

Hadar Bejerano: That’s a really good question. So one of the secrets of doing a good hackathon is actually to get some time added from all sorts of areas.

I would say that one of the things that I would recommend people that are in process of going into a hackathon to do is try to have an idea in mind and also try to have a working environment in mind. Just like even if you didn’t write a single line of code for that specific project, but [00:13:00] if you have already the framework that you’re going to use already up and running in your computer, already compiling, you can already get something basic to work, then you are, you might be saving like six hours of trying to have that done under the pressure of the hackathon day.

So I guess we did a bit of that but most of the code was, and you’ll see in a second when we’ll go over it, we tried to reuse existing libraries. So we don’t need to write a lot of code. Eventually we try to use frameworks that are powerful. So using all of this actually made it possible to write most of the project within the hackathon timeline.

Jen Brissman: Wow. Okay, cool. Let’s get into it. Let’s see what you guys built.

Hadar Bejerano: Actually what I’m showing you right now is just, if you want to learn more about Cloudinary [00:14:00] hackathons, these are just blog posts that we put out to talk about hackathons that have been done. So the latest hackathon that was done was even around a different area, which is Generative AI.

So you can read all about it there. You mentioned Cloudinary Labs already. This project is inside the Cloudinary Labs. And if we go into Cloudinary Labs and inside Extensibility, then you have the link to go into the GitHub and and see the code of Cloudy Desktop. Now, before, actually going into the code, I’ll just show you how it actually works so you can see it in action, and then we can go and dive into that- all the details. So for that, I’ll move into the Cloudinary console. But just to mention one more thing before. [00:15:00] As I said, in order to try and just write the code that we need for the project, we tried using existing libraries and existing components that can power this project so you don’t need to write everything from scratch.

One of a very powerful tool that is part of the Cloudinary formal, released to customers, components is the Cloudinary CLI module, which means it’s a Command Line based Interface (CLI) interface that you can use to invoke and to run all sorts of commands. You don’t have to write code there. You can just run it from the shell.

So it’s very powerful for IT people. It’s also very powerful in this case because we are using it under the hood. So again, just to also mention that as one of the components that powers the platform and then Thank you. We’ll jump into the demo.[00:16:00]

Sam Brace: I agree. With the CLI, by the way… like it’s one of those things where the more that I’ve seen people using Cloudinary, it’s where many cases our SDKs are very powerful, but it also sometimes takes a second to write scripts for it, to be able to get it all up and going. The fact that you can do quick commands with the CLI the way that you’ve been able to knock this out is something that’s truly fantastic.

So a big shout out to everybody that worked on the CLI development because not only is it helping the power of the Cloudy Desktop, but man, what a cool tool. Our CLI is pretty awesome.

Hadar Bejerano: Yeah. And do check it out because it has actually higher level functionality than the APIs. So the APIs are the basis of everything.

And the CLI actually implemented some even higher level function . So let’s go into the actual demo of Cloudy Desktop. So what I’m doing right now is I’m showing you the Cloudinary Media Library. Hopefully you’ve used Cloudinary already and you are familiar [00:17:00] with that. And as you can see, as a graphic designer, I just created these five amazing work of art. I don’t know where I got the inspiration for, I’m about to do the next one, right? So then to do the next in line, which I guess you, you can know what it would be. And that would be the number six in the dice. What? What I want is instead of me going back and forth, uploading and updating Cloudinary, I want all of this to be done automated. So let’s look into a Cloudy Desktop. As I said, Cloudy Desktop is an app. So you can see I have an icon. It’s an app. It looks like a standard Mac app. I’ll run it. And it opens rather small because the UI here is not intended for ongoing use.

You just need to [00:18:00] configure it once, and once it’s configured, you leave it as is. You can here put the parameters of your API, so of the Cloudinary API. So it’s a Cloud Name, the API Key, and the API Secret. And we’ll talk later on the developer part of how you do this really in a secure way. And next, you need to configure two folders.

One folder would be the local folder on your local machine, which you want to sync to Cloudinary. And so this is where I select a folder here. And you can see that I can open the dialogue to do this. Or I can second, I need to select it if I did it. And second is I have the Cloudinary path to the Cloudinary folder inside Cloudinary. And Cloudy [00:19:00] Desktop will always save files into a folder under Cloudy Desktop folder so we don’t by accident overwrite some folder we didn’t anticipate would be there. So I created a folder called also local dir inside the Cloudy Desktop folder. So if I now go back into my view of the console, then here I have my folder here, so let’s run Cloudy Desktop, and once I run it, it will start working automatically for me.

So I’m running it now, and you can see that it says Sync On, and now, I cannot change the folders anymore, because if I want to change, I need to stop it first. And it will now start to listening in on changes that I’m doing on the local folder. Okay, so [00:20:00] far?

Jen Brissman: Yep.

Sam Brace: Makes sense.

Hadar Bejerano: So let’s go back to our local dir, and let’s put this aside for a second.

And now I’ve done my amazing work and I’m ready to publish my dice number six, and I’m putting it here in my local folder. So just putting it there. What happens in the background is that Cloudinary is running. So it detects that this is happening, and let’s refresh and see if this was actually updated. Yes!

Sam Brace: It was. That’s great.

Hadar Bejerano: And easy to see that number six is now there. Now that was a really basic kind of a thing, right? Just another file, but it’s not limited to that. I [00:21:00] can also drag. So I have a folder here. A folder that includes other folder and other images. So maybe I’m dragging all of this also here.

So again, it will detect that, automatically update it, going back to Cloudinary again. Let’s see where we are. Let’s refresh the screen. And yeah, we have another directory here. And in that directory, we have our file that were there. And that other file as well. So everything is updated and I haven’t needed to go back and forth doing it manually.

Sam Brace: Very cool.

Jen Brissman: Thanks for doing that demo. Cause you know, really it, it, if the picture speaks a thousand words, a demo speaks a million words. Cause we see exactly how this works and it’s so clean and really people don’t want to do anything manually and this isn’t new, but [00:22:00] this is just a great tool for anyone who does do a lot of either migrating or just uploading to Cloudinary for them to just do it in a single drag and drop of a folder.

And for people who are a little maybe not as technical or would rather work in a CLI or like the idea of not having to use code to do these things, someone who’s a DAM administrator could absolutely do this no problem at all. Or someone technical who just wants to do a drag and drop and doesn’t feel like writing code that day.

Sam Brace: All right. Yeah so, Jen – I’m sure we were all – we have all the same question. How did you build it?

Jen Brissman: How’d you do it? Let’s see under the hood.

Hadar Bejerano: Amazing. So – great question. And I apparently by coincidence, I have all the code here. So, a gain, as we, we already said the same code that we are going to review now is actually being able to be compiled to both Mac and Windows.

So you’re… [00:23:00] so if I have a colleague that wants to do the same thing, using Windows, you can do this as well. So all of this magic starts with a really cool framework – a JavaScript framework called Electron. And when I was thinking about this hackathon, really, I was looking to try and use the code that I use in my day to day. And Cloudinary’s day to day is usually around web development.

So what we use, the CSS, HTML, JavaScript, all of these development technologies that are not part of native desktop development, right? Usually, if you want to write a Windows app, I would now need to open a .NET application or an Xcode application Mac and write in different languages that, that maybe I haven’t used for a while and all of that.

It’s really [00:24:00] amazing to find Electron as a really stable and useful framework that just gives you the option to reuse the code that you have with JavaScript, with HTML, with CSS, with all of that. But as it says here, but still build the cross platform desktop application. And and it’s not only me doing this, right?

You can see that this tool is already have built some applications that I’m sure all of you know. Visual Studio Code is built with Electron and Slack is built with Electron and many other examples that you see here that you might be using already like Postman and so on.

And by the way, if you have… now that you’ve seen this list, if you compare how the web interface of those application looks to the native interface, you would see they are very [00:25:00] similar. And this is because it wasn’t redeveloped. It really was ported using Electron to be a desktop app.

Sam Brace: This is very cool. And enlightening, frankly. It’s like you’re pulling back the curtain on a lot of this overall development. We’re like, hey, did you know it’s done with Electron? So this by itself is interesting.

Hadar Bejerano: Yeah. And then, and you write UI, you write desktop UI with CSS and HTML, and you’re like “what, how is this going on?”

But yeah, all the praise goes to Electron, which is a platform by OpenJS really cool tool to use. And next is so let’s look into the, into, no, let’s go up and also look into the code for a second. So I just wanted to explain a bit what Electron is. What Electron actually does is open [00:26:00] a Chromium window.

So it’s a Chromium, let’s say, engine window. And this is why it can run HTML and CSS and JavaScript understand what it means. It’s like opening a browser window within the desktop, let’s say, environment, and it holds the best of two worlds. One is the frontend world, which is CSS, HTML, JavaScript and the other side is also the Node.js.

So you can also do all the stuff that you do with backend code can be done with Electron as well. So you have the powers of both these infrastructures.

Sam Brace: Very nice.

Hadar Bejerano: Next is to understand a bit the architecture of Electron. So just again going here in this article to another diagram that they created.

So Electron in [00:27:00] basics works like you have one main process and then that process will go and generate let’s say windows. And each window that it created, it’s called the render process, and it will have its own HTML that actually defines how the window looks. So in the application, we will see the Cloudy Desktop, it has only one renderer. But you will see that we will start with talking about the main process, which is the main application, and then going into talking about how we create the renderer process and actually build the UI for the application.

Sam Brace: Got it.

Hadar Bejerano: We understand so far, or we are good?

Cool. I want to show you this image because it was so funny for me. I was starting to write this code. I [00:28:00] went across a blog post just saying how to write Electron correctly. And they had this image that stuck in my head like they were saying “just don’t write the code in this way because it has this Size of a security vulnerability in it” And I was like, “Okay. Okay. I’m not going to do anything that looks like this.”

What is this vulnerability he talks about and I think It’s already disabled in latest Electron versions, but just to be aware, they have… they want the communication between the renderer and the main process to be done in a certain way that that is secure.

So former Electron version was open to really just sending messages as much as you want. And you could even see code samples that you would just send message all the time between two processes. The right way to do things is actually to try and keep each side independent as [00:29:00] you can.

So you run the main. It does what it does, and you run the renderer, it does what it does, and you try for them not to keep talking to each other. If there is some functionality that needs to be there, just move it to the right process. And there are some functionalities that only the main can do. For example, only the main can open the dialogue that you’ve seen me opening of the finder of the folder of the of the local desktop, right?

Because there are some functionalities that are restricted from a browser window. And then there is a function that you can do that in a secure way – we will go over it. But just remember, have the track in mind and remember, write the main process and the renderer as independent as possible. And if they do need to communicate, then there is a way, it’s called an Invoke API, where you can actually call a function from renderer that will run on the main.[00:30:00]

Sam Brace: Got it. You’re helping with a lot of concepts here.

Hadar Bejerano: Amazing. So let’s go into the code. So because this is built on JavaScript and because it starts from kind of Node.js infrastructure. Then this starts from the well known package. json file. So that’s a Node.js configuration file. And in essence, the one thing that is important here right now is just to say, “okay, where do I start?”

So you start here. Your main component that we just talked about, the main process, is written in main.js. Okay, it’s easy to keep the same name. You can write any name that you want. But so we now know where, when we go and review the code, we know where to start looking. We want to go first to main.js, which will be the JavaScript that will tell us how exactly the main [00:31:00] process. Now that we are inside main.js, we can see that it’s Node.js, Node.js code. What I’m doing is going to require the Electron npm package, and I’m going to ask for specific modules that I’m going to use throughout this code, but you’ll see eventually it’s pretty short code and electron really gives me the models that can do what I need.

Next thing that I’m doing here is that I, because we are writing code that eventually will be compiled to do different desktop environment, Windows and Mac, there are some points in the code that you want to do differently. For example, just a basic thing. If I go to a Mac application and I close it, it doesn’t really close, right?

Sam Brace: Right.

Hadar Bejerano: It goes down into the dock. And now [00:32:00] here in the dock, I have a quit option. And in windows, if you close it, it’s really closes. So you have these different nuances on how the app should behave and you will, and we will go over it. We will, you will see that you write code that controls it, but just for me to have these variables that are easy to use, I’m just checking “is it Mac or is it Windows?” And I’ll use this Boolean to tell me. Or I could just check, because part of what Electron gives to me is this process.platform variable that tells me which platform it is. Next, I’m jumping a bit forward to just show you the main thing here.

Main would next would be that you, you seen that I took a model from electron that is called app and app is my main app thing. [00:33:00] And what I want to do with app is actually to add a listener here for when it’s ready to start, and when it’s ready to start, it needs to run the function that I define here.

In this case, I’m defining a function called startApp. So this is actually the first thing that’s going to happen is that the operating system will tell the application “you’re ready” and then the application will go “okay, I need to run startApp”. And then what startApp does is the first thing that he does is createWindow and what createWindow does is creating that browser window. Okay. It’ll create that window, which will actually will be that render process that we talked about. So it’ll have an HTML file that defines how it looks, because this main component doesn’t have a UI, it just runs in the background as a server in the background, that, that spawns [00:34:00] the windows.

And now it’s going to generate a window. I define the sizes. I can define if it’s resizable or not. In my case, I did very basic CSS and HTML. So I didn’t want it to be resizable. But you can write it in a way that you know, like you build a proper responsive website, you can write it in a way that it will be resizable.

And also some, some functionality here to define if I’m using or not, and at the end of the day, it just defined this, that I’m going to have this size of a window that I cannot resize in my case. And we’ll see in a second also that it loads this file. Which will be my HTML file that will define exactly how this window looks.

So as you could see, my main code created the [00:35:00] main process that can create one window or more in my case one, by calling the browser window and defining which HTML it will run and what would be decided.

Sam Brace: Incredible. Incredible. And the great thing about what you’re doing here, Hadar, in my opinion, is that it’s not only where we’re walking through how you built this project that’s going to be using Cloudinary, but this is an amazing primer for anybody that’s doing any Electron app in general.

So it’s this is, you’re getting two awesome tutorials in one with this episode here. So far, so good. Excellent work, Hadar.

Hadar Bejerano: Amazing. Thank you. Another cool thing about Electron and the fact that this is actually a browser run window. Is the fact that if you are using Chrome, right? And you want to check stuff in your Chrome application you can open DevTools, and you can start debug [00:36:00] your website.

Sam Brace: This is the part that blew me away. When I first saw Cloudy Desktop, when you saw, you could actually pop open DevTools inside of this. This is, that’s cool.

Hadar Bejerano: Yeah, so the reason I can do it is exactly this code here. I can decide to disable it, right? If I now go to to Slack or to Visual Studio Code, a production version, I won’t be able to open the DevTools because probably it’s disabled.

And so they probably have “devTools: false” on the code. But here you can see it’s remarked. And therefore I can go and open the DevTools in the same way that you would open DevTools on your Chrome. And I can go between the different elements and I can see all the messages that were sent to me throughout the sync process, right?

So we learned the sync before. So all of this was a print to console. And I could debug this if I had any [00:37:00] issues, if there were any problems with the sync, or I can look back into the element in the HTML and see if it’s, if I have any UI, CSS issues, I want to, and if I’m doing any network, all of that is available to me. So again, as someone who is used to work with their web environment, you get all the tools that you’re used to.

Sam Brace: What a wonderful way to make sure you are able to troubleshoot. I think the example you had, Jen, about Let’s say that as a DAM administrator, you want to get this on everybody’s computers. It’s going to be putting things into the DAM, make sure you’re syncing to the right folders. Let’s say that somebody’s saying it’s not syncing or something like that. You can go immediately and troubleshoot for them inside of this. So this is great that they have this backward looking capability where you don’t always have to say, this may not be a issue that’s inside of the JavaScript.

It might be because of something that’s tied to their desktop itself. I think this is great.

Jen Brissman: And because the width [00:38:00] and height are specified as 750 and 620, if you were to try to resize this window right now to show the DevTools bigger, it wouldn’t work, right? Because it’s not responsive?

Hadar Bejerano: Yeah. Yeah. So I would, let’s say, I would run it resizable too if I need it to be with bigger DevTools. So I don’t need to do everything in my, in that 750 size, yeah.

Jen Brissman: Okay, cool. Good to know.

Hadar Bejerano: Cool. So you think what I’m actually doing in the main is mainly just defining the window, defining the file that it’s going to run. And then again, as I mentioned earlier, I will do stuff that is around getting all the events on the windows and handling them a bit differently between a Mac and Windows. So here, for example, if I get a close event, I’m actually not going to close it but just going to resize it. But if it’s Windows, it will go and [00:39:00] resize.

So other than handling these events on the windows and running the browser window, that’s pretty much what what the main application does. So let’s jump and go into the index file. So let’s see what the browser does. So here again, I just have a, I just have a HTML that defines exactly what we just seen…this UI.

And there is also a CSS file. So again, above here, there is include to a CSS file and there is also a JavaScript file. So here I have a CSS file and here at the bottom I have a JavaScript file that will run the actual functionality. So let’s jump into index.js, which would be the JavaScript file that would actually run the functionality here.

So I’m going [00:40:00] into renderer and inside there is index.js. Here what I want to do is to do the functionalities that we’ve seen in the demo. First, what I want to do is I want to be able to read the parameters of the Cloudinary account, right? In order to be able to communicate and to upload files to Cloudinary and to have full access and full control. I have here the Cloud Name, the API Key and the API Secret. So I want to, I don’t want to retype them again and again each time I’m opening this app. I want it to be stored and when I open it to read it from somewhere. So I’m actually each time this is being updated and save is clicked, it saves to two different stores of variables. One is let’s say a regular store of information [00:41:00] for Electron and the other one is the secure one for the password. So you can see that I’m defining here a store that will use a library called the Electron store. And then I’m for the secure one, I’ll use a specific library for passwords called keytar.

So let’s look at the store at first. So you can see that I just doing get of all the information that I need. So if it was already there, already saved, I just get it. Where do I get it from? Let’s see how this Electron store looks like. Let’s just find it here. I have it here.

Jen Brissman: So many tabs.

Hadar Bejerano: Yes. Ah, Electron store. Okay. So Electron store shared the source as you can see here in the README. [00:42:00] It allows you to read and write data, so it will be persistent. The data is saved in a JSON file, and this is why I’m not saving the password there. Just saving the other data that is open. And it’s also can work in Electron in both Windows and Mac.

So make it super easy for me. And you can see I have the code example here. I either set or I get. That’s it. It makes my life easier. So all the parameters that I have here, the Cloud Name, the API Key, the API Secret, not the API Secret, the local path, the Cloud Name path, all the parameters that I need locally here, apart from the API secret, I just use Electron store, get and set, and I’m done.

If I don’t have anything, then this would be open and empty. If I do have something, I’m reading it as I’m coming up.

Next, I want to [00:43:00] do the secret. So again, it can be a very complicated job to store variables locally in a secure manner, right? So the API secret in Cloudinary should be stored securely. Actually some of the functionality sometimes you can do in Cloudinary, you don’t need to use the secret at all. So you can also upload to an outside preset that we have options to do it.

But in this case, we gave full control for the app. So we just need to store the secret securely. So how do we do this? Again, luckily, there is an existing library that does this work for you and open in NPM called the keytar. You can see a lot of downloads, which usually gives a good indication that you are on to a reliable source.

And what [00:44:00] keytar does is, as it says here, it uses, in macOS, it uses the keychain, and in Windows, it uses the credential vault. These are just two repositories that are managed by the operating systems. They are there for that exact reason. You can store data in a secured way. So if I’m just, coming into this desktop, not as the application, but just looking for the data to find it because I have a virus and it search for stuff on my folders, stuff like that, you won’t find it.

All right. So the data is secured. The app can retrieve it. You don’t, you won’t find it in a JSON file like the other files.

Sam Brace: This is excellent. Absolutely. And it’s something that I know me and Jen preach constantly in courses is like, “When you’re doing anything that’s server side with our API secrets, you got to put it in an ENV file, or you got to make sure that it’s not exposed in client side code”.

So once again, security: [00:45:00] vitally important to working with anything in Cloudinary, and I’m glad that you addressed it in this project.

Hadar Bejerano: And the number one thing you don’t want to do with this secret is to put it in GitHub.

Sam Brace: That’s right.

Jen Brissman: Don’t check that in.

Hadar Bejerano: It’s there for, it’s hard to get down. So yes.

Sam Brace: The general rule of once you put something out on the Internet, it’s very hard to remove it from the Internet.

That includes your API Secret. So yes, very good point, Hadar..

Hadar Bejerano: Even if you delete it afterwards, it’s in the history. So we’ve seen that what the renderer does is it reads all the variables. And then the other thing that it does actually it would go and use these variables in order to run the sync itself. But luckily, I don’t even need to implement the sync myself because you’ve seen Cloudinary CLI.

We mentioned that. So Cloudinary CLI already have a function that [00:46:00] will run and sync, but the only point is that it will do it one time. So what I need to do is I need to do two actions. I need first to listen in to any changes in the folder. And once I have noticed that there is a change in the folder, I can run CLI to update the entire folder to Cloudinary,. So how do I listen into changes in the folder? Luckily, again, there is another library that I can use, which is called chokidar. So going back to NPM, going back to chokidar again, we have increased the number of downloads by, so this is 44 million downloads.

So again, you can see it’s a really good and used by many to do exactly that. It can go and watch all types of events that folder has [00:47:00] so we can know about everything. If a file is added, deleted, folder added, file was updated, all of these events. You get as events in the code so you can listen to those that you want to respond to and do something about it.

So here what I actually do is exactly that. I just build a watcher that is based on that library and I’m just listening to all these different events that I want to be aware of ,that I want to go and perform a sync because they happened. Each one of these events will actually go and make me do the same thing: run the CLI so that it will sync between the local path and the Cloudinary path.

Jen Brissman: So once you’ve started up the app, is it always going to be listening because of chokidar? If for any changes, it’s watching, it’s listening, how often does this update? And do you need to close it down completely for it to stop listening [00:48:00] for changes?

Hadar Bejerano: Great question. So you can see that here I have the status defined. So right now it says Sync On. So it means that it is listening and any change that I will do will be detected and updated. When we started when we just initiated it, it wasn’t on yet. So you need to click it once to run it. There is also this amazing rotating arrows, if you can see it, that shows that it is in action.

And, but if I want to, if I want to stop sync, I have here, inside the dock menu, I have a stop sync option, and you can see that it stopped, and now it’s waiting for me to, and now it also allows me to change the folder again. So the folders were disabled, and once I stopped syncing, I can change the folder if I need, and I can click sync.

Jen Brissman: And is it immediate? Just say you make a change like you demoed before. Is it every [00:49:00] second, every five seconds? Okay.

Hadar Bejerano: Ah, so once I run, once the sync is on, then any change that I do will trigger the event here immediately.

Jen Brissman: Yes. Okay.

Hadar Bejerano: So it doesn’t wait for every hour, every two hours. It is constantly immediate update on this.

Jen Brissman: Yeah, cool.

Sam Brace: I like that. And what’s cool about that to me is that it acts very much as that single source of truth concept where whatever is in your Cloudinary DAM, whatever’s in your Cloudinary account, whatever is in your product environment, whatever we’re going to be classifying this Cloudinary storage aspect as, it’s where whatever you need to be in it is there at all times.

So I think to our original point, if you install this on some multiple computers, the people that are working on Cloudinary environments. They always know that whatever is the latest, the greatest, the most important things, they’re in that area. There’s no waiting period where you have to suddenly [00:50:00] say “well, at the top of the hour, it’s going to be correct.”

Yeah it’s what’s there, is what’s there. So I like the fact that you make this listening and actionable at all times.

Hadar Bejerano: And now, as you saw, every event drives the same function, which we saw is runCliSync. And that is running the Cloudinary CLI. So I’m spawning. Once it’s installed, and you’ll see that in the packaging, I’m actually installing it.

But once it’s installed, then in the terminal, you call it as CLD. And there is a sync function. Part of the CLI, this is what I mentioned that it has a higher level of functionality than our regular API, because it has a sync option. But it just runs once, and again, as I said, we are listening to events and then running it.

That would be the trigger for it. I have all sorts of options here that are command line based, that I’m just building the right function that I want to want to run. So I want to be pushing form local [00:51:00] to Cloudinary. I want to make sure that it’s getting updated. And I want, keep-unique means that even if I delete files locally, I won’t delete them from Cloudinary.

So I’m just keeping there. Maybe you delete it by accident. I’m just keeping the stuff but this is, can be changed. But this is the option that for this project we use.

And again, this CLI function just from the command line can be run by any, anyone that installed the CLI, go to the command line and build this and run it if you want to do it manually. Cool. So yeah, in essence, this is the app. Usually, this is where it ends. But here, because it is a desktop app, you now go into the amazing world of redistribution. You now need to take this code and actually make it into an executable [00:52:00] file that can be used by both Mac and Windows. In the old days, I could, FTP use a file today you can’t do it anymore. The operating system is protecting itself, so one way, let’s say the best way, would be to go and take this into the process of registering this app in the store.

So the Windows store would have Cloudy Desktop and the Mac store would have Cloudy Desktop, this won’t happen in 24 hours in the hackathon. They also haven’t happened in this case. I did do some of the work after the hackathon of packaging, which will go over but haven’t got to the level of putting it on the store. So actually in Mac, there is one level before that, where you can build a package that you can [00:53:00] redistribute by yourself and sign it so that the operating system is allowing you to run it as well .

Sam Brace: Right – and which it makes sense because you don’t want to be having put in malicious material into anybody’s computers.

And obviously, it’s in the best interest of these OS creators, Microsoft, Apple, to make sure that they’re not allowing for easy pathways for that to happen. So it makes sense and I agree with the steps to take to make sure that your application is able to be used by all.

Hadar Bejerano: Cool. So to see that, to learn a bit about that, we go back to our package.json configuration file. So far we just talked about main.js.

Sam Brace: Yep.

Hadar Bejerano: Now you can see these bunch of scripts, that will actually help me to go and build a file that I can redistribute so that you can now download from GitHub, install it. And you still would need to tell [00:54:00] your Mac operating system to allow third party applications because by default it only allows from the store, but once you tell the yes on that, it’ll let you install. And you also know that is that it was checked and found okay. So what you need to do is get the app both signed and notarized.

So let’s explain what signed means, and what notarized means. Signed means that you are a developer that have an account with, the Mac developer, and that you’re registered and they know who you are and you got a certificate from them. And you need to pay for that, an annual fee, but Cloudinary has that certificate.

So I’m using the Cloudinary certificate. Any developer can just register and get certified based on their process. So you get a certification. So you know who [00:55:00] you are. So this is getting the code signed, which means you put your name on to that code, so if there are issues, they know to track it down. They know who you are. What notarized means is that it’s actually you take the app, you don’t go to the full process of submitting it to the store, but there is a shorter process of they just you send the app to the Mac servers, to the Apple servers, and they will do a short review, just making sure you don’t have malware.

So signing means I’m putting my name on it, I’m certifying it with my certification. Notarizing means that I have sent it to Apple, they checked that there is no malware on it, and approved it.

Sam Brace: I like it. This seems to be, “trust, but verify” the way that I’m looking at this is “yeah, we trust you. You’re Hadar.” You’re saying that, obviously you put your work into this, but we got to still check, you make sure. So I like this code [00:56:00] plus notarization aspect to it. So this is good.

Hadar Bejerano: Yeah. And as it mentioned there, if you are going to eventually send it to the store, then you have a process to be approved in the store and then you don’t need it to be notarized because they will do additional checks there. But not our case. So we are going to do both signing and notarizing. Going back to our code, and let’s do signing first. As I mentioned, I need to have a certificate. So I need to go to Apple Developers Community, sign up, get a certificate, pay them the annual fee. Cloudinary, luckily did this already. So I’m using their certificate and I’m using a tool called package build that will actually create a .pkg [00:57:00] file. A file for installation on Mac because my file right now is a .app. It’s an app. In Windows, it would be a .XF. But I want to create a file for installation.

So this tool will create a .pkg file. Now there is another way to do this. There is also a tool called the Electron forge that actually do all the work for you. I haven’t used that tool, so I won’t go into the detail of that. Just be aware, you can also use Electron Forge. I’m using the lower level tools of the operating system of, so package build is in Mac.

The other one is product build. What is the difference between these two? What package build will do is create a, as we said, a .pkg file, and sign it with your certification. What product build will do, which you run after the package build is it adds additional [00:58:00] resources on top of it.

Because first, your installation package can have more than one package, if you have several components. So a product is built of several packages. And second, a product also includes additional resources. For example, the message that you show to the people starting to install, and we’ll see it in a second.

So there is an HTML file with that message. The message that you say at the end of these definitions. So you can see here that I have a file called the product.dist that if we go into that, actually define messages. If I go into build, then you can see that there is a file called welcome at the start, and a file called conclusion at the end, of this file will be shown at the start and at the end of the installation.

And I [00:59:00] just see an example of installation. So I have here the package. So if I double click in the package, you can see it starts the installation. Let’s see if I can. This one is also you cannot reset. It starts the process, and it will say, this will install Cloudy Desktop on your computer. So this actually text comes from the welcome HTML.

And when I continue and end up with whatever it needs, and at the end it will show me the summary.

Let’s run very quickly. So we created that package saw, and we built. So it was two step, we built it to something that you can run. You still need to authorize it. So there is this tool from Xcode that runs an authorization, and you tell the, you tell it where the package is.

It actually takes time. So you run the command. It takes time for it to give you back a response. So you just sign it on the terminal and you wait. [01:00:00] It submits this file to Apple. It’s getting files all the time. So in I, I think in an hour you get a response back. “Yeah we reviewed it, we didn’t find any malware.”

You get back the file with the authorization on it, and you’re done. And now you have the .pkg file like I just showed you. Any one of you can now go into GitHub and going to release us here and find it. So you can download it and install, or you can also, as is explained in the in the README, or you can just get all the code as it is, and compile it yourself. So this is also explained On the readme so you either get the pkg and install it or you get the code and compile it.

Sam Brace: Incredible. From top to bottom. This is great work, [01:01:00] Hadar. Very great work. And like we were saying now we have very comprehensive view of some ways to streamline work that you have with Cloudinary, but also ways to be able to say, if I need to create some form of a desktop application and do this with basic HTML, CSS, JavaScript, how can I possibly pull this off? You’re doing that with Electron. You’ve shown a lot of different opportunities here.

So this is excellent review. Is there any best practices, anything that you said, if I didn’t do this step, it would have gone poorly, or if you were to do Cloudy Desktop again as a second iteration, would there be anything that you would have done differently?

Hadar Bejerano: I think the point… that kind of helped is, as I mentioned earlier , just to get something basic working first.

So I had, I used the code samples that Electron gives that are very useful. It just had some, basic window open. And then as I [01:02:00] was reading about it, I came across that blog that said, “Oh, don’t do this, do that”. But it’s actually, I think the main decision that was important here is just using Electron, right?

If I would go through any other framework to try and write it, which are native desktop options, I probably would have taken a lot more time. So I guess choosing the right framework and the right libraries is key. No, I wouldn’t build it right now differently, but but there was a lot of thought was go into that before we actually started the hackathon itself.

Sam Brace: Makes sense, . So Hadar, we’ve covered a lot here today. And obviously, there’s going to be a situation where someone’s going to take your work and try to do something with it. They’re going to install it, just run it as is, or they’re going to try to do something [01:03:00] with the repository that you have here.

Where can people go for more questions? I see that obviously you’re on GitHub here as one of the contributors. Is that the best spot? Is there ever places where you can be, you’re actively reached by your listening and watching population?

Hadar Bejerano: Yeah, so I was joking around with Jen earlier saying they can send a fax to me, but probably that’s that’s not useful anymore.

Just kidding. Yeah I’m available on LinkedIn. And happy for people to connect and to join and to start a discussion. It would be great if people will actually try this. Any questions that they have either on Cloudinary in general, or Cloudy Desktop, or what I can answer on Electron, I’ll be happy to, for people to, to connect and to continue the discussion.

Sam Brace: Wonderful. Hadar, this has been fantastic. Thank you for coming on the program and being a part of this. We can’t wait to see what else you’re doing. I know that as we pointed out at the very beginning of the program, you’re [01:04:00] working with some of the best and brightest at Cloudinary and our solutions engineering team.

So it can’t be just where you’re the only one making great stuff. There’s probably things that your team is making on the daily. So keep us updated on all the happenings within your team. And hopefully we can have you guys come back for another DevJams episode.

Hadar Bejerano: Amazing. The team is doing much better work.

So for sure you should see what they are doing. But yeah, it was great joining you and thank you for having me.

Sam Brace: Absolutely. Thank you, Hadar.

Jen Brissman: Thanks for coming.

Sam Brace: So what I want to ask is, Jen, what’s your big takeaway here? What’s the thing that stood out to you about Hadar’s awesome work here with Cloudy Desktop?

Jen Brissman: So aside from his demo, which was really thorough, we really left no stone unturned and anyone can watch and really learn some things. He even mentioned, “Oh, we didn’t use Electron Forge, but you could”. So he really has a lot of helpful nuggets within his demo. But I think the biggest takeaway for me is the Cloudinary CLI.

It’s fully supported by [01:05:00] Cloudinary. I didn’t even know that there’s a higher level of functionality with the Cloudinary CLI than our SDKs. I don’t know exactly what that meant, but it just makes me wonder about the CLI and really want to get my hands dirty and work with it more. And – no code.

There are so many attractive factors about the Cloudinary CLI. And so I think this is our first real project that we featured that is working with the CLI in a big way. Am I missing anything, Sam, there? Or is this really…

Sam Brace: Oh no. Yeah. This is probably one of the first major ones that we have on a DevJams episodes, for sure.

Jen Brissman: Yeah. So I think my biggest takeaway is just, wow the Cloudinary CLI is powerful and should not be overlooked and is available and fully supported. That’s a big takeaway. And then I guess the other thing that we did touch on throughout the episode is: hackathons. And a lot can be created in a short amount of time, and I think it’s awesome that Cloudinary has this hackathon culture that is exciting here that we do internally, especially, but also as Hadar was mentioning, [01:06:00] there are other forms of hackathons that we do. It’s just, it’s cool that this was built at a hackathon and now it’s featured on Cloudinary Labs. So that’s another

takeaway for me.

Sam Brace: What an amazing segue to be able to talk about Cloudinary Labs, because that is where all of these projects that have come up from labs have come up in some form of a hackathon that Cloudinary has supported of its employees. So definitely go and check out exactly what Jen has mentioned all of the projects that have been the best and brightest of those hackathons over at And also, I’ll completely reiterate what you just said. Our CLI is crazy powerful. Crazy powerful. It’s where if you’re a developer and you’re saying, okay, I’m using one of their SDKs, let’s say Python in this case, because their CLI is a Python based application. And then we have the CLI.

Now you’re able to do very quick situations where you can easily just run things command line. You have your full forged [01:07:00] SDK, but then you can also do things like what Hadar has done and really empower your entire team to have streamlined uploads and management of all the files that they need to be able to deliver with Cloudinary.

So there’s a lot of connectivity here with all of the things and all the different types of personas that really care about digital asset management. Whether it’s going to be images, videos, things that you’re going to put on your website, your mobile app, whatever it happens to be. There’s a lot of streamline here that Hadar created, which I’m very happy to show off.

The other big thing, of course, as we’ve said a few cases, make sure you are checking out that GitHub repo that Hadar has gone and put out there. You can see here that project, as well as all of the lab projects that we talked about. It’s just going to be a, and you can see all of those happen to be there inside of that overall space.

On top of all of this, make sure that you are checking out all of the podcast episodes because me and Jen have been [01:08:00] producing these things for quite a while. You can find all of the episodes, of course, listed at On top of that, you can always find all of our podcast episodes, wherever you probably like listening and watching podcasts.

So that’s Apple podcasts, Google podcasts, Spotify, YouTube, and also our Cloudinary Academy, which is where you’ll find many training resources and courses also happen to house all of our podcasts as well. And of course we have to mention our amazing and vastly growing Cloudinary community. So if you are wanting to be part of these conversations, let people know about the great work that you’re doing, maybe asking questions of Cloudinary employees and staff and users about some of the projects that you hear about here on DevJams. You can always do so at — Wait, I will get that. And of course we have an associated Discord server, which you can always find linked inside of that space.

So – [01:09:00] Jen, any final thoughts before we let our audience go and have a wonderful day?

Jen Brissman: Yeah, I was just thinking, get this going, you’ve watched this whole episode. You’ve gotten to this point, get Cloudy Desktop going for yourself because, using Cloudinary CLI to automatically sync a local folder into the cloud and into a Cloudinary folder, that’s a very common use case. I know as a Cloudinary employee myself and with the work that I do at Cloudinary, I’m always making uploads to Cloudinary and I’m thinking just throughout this episode, why haven’t I gotten Cloudy Desktop going? I think that’s what I’m doing as soon as we finish this episode.

So if you’re watching, if you’ve gotten to this point, if you’ve watched Hadar’s awesome demo throughout this episode, get it going for yourself and let us know what you think.

Sam Brace: I love it. I love it. I like the call to action. Good job. Yeah.

Jen Brissman: Listen, you’ve gotta.

Sam Brace: So on behalf of everybody here at Cloudinary, including myself, Jen and Hadar, thank you for being a part of this DevJams episode, and we can’t wait to show [01:10:00] you what else developers are doing when they’re pushing the boundaries of image and video delivery, management in their own projects, hopefully with Cloudinary as part of it. Take care, and we’ll hope to see you at the next episode.