Best way to add photos to the RedwoodJS Blog?

I’m going through the second part of the RedwoodJS tutorial, but it dawned on me that a blog normally has photos. What’s the best way to add photos to the blog?

I would like to be able to edit the page, add certain photos to it, or delete at will. To me, you probably wouldn’t store the photos themselves in the database like the rest of the Comments, or Posts objects, maybe you would store a link to it?

I’m new to the Javascript APIs Markdown Stack (JAMStack), so any info on this is appreciated! It makes sense to have photos on many different types of websites (probably any site needs photos) from e-commerce to social media to tutorials like RedwoodJS’s, so this could be a ripe place to expand the main tutorial.

I’d use an image host like ImageKit, and then, as you say, store the url in the database

1 Like

@lancelot you just hit my “sweet spot” as adding photos to a blog was the reason I discovered RWJS. My long-time dream is to create a very sophisticated application of the type “family genealogical tree” mixed with blog-like content. I plan to use a self-hosted ghost blog and discourse forum, integrated via the RWJS based application. The question of where to maintain images was on my mind for a long time until I discovered cloudinary - see Build a Gatsby Photo Gallery with Strapi and Cloudinary for some ideas how can do that. Note that my plans ar more ambitious as my ancestors can be traced back to the late 15-th century :grinning:.

1 Like

P.S. Upon a closer examination of imagekit.io, I am not so sure that I will not change my current plan (thanks @Tobbe)

1 Like

We have the blog as more complete sample repo and it includes image uploading. We used Filestack: GitHub - redwoodjs/example-blog: Example Blog app written with Redwood

It’s probably a couple of versions behind and could use an update!

We’ve also got a cookbook recipe just for file uploads: Cookbook - File Uploads : RedwoodJS Docs

1 Like

Hey @adriatic that sounds like a great application of Redwood. I can’t imagine having documented a genealogy that goes back to the 15th century; incredible. Would love to see this once you get it built :slight_smile:

Thanks for those links too. Cloudinary’s API seems interesting, and I started reading the Build a Gatsby Photo Gallery post… but am trying to avoid adding another framework into the mix. Still, it’s tempting Strapi’s interface seemed great with only a few clicks.

Thanks for the response!

Hi @rob thanks for those links! I didn’t know about that example blog, but it seems it will answer many of the questions I had. As soon as I complete the Revenge of Redwood tutorial, I’m going to dive further into this repo to re-engineer how you all did this.

It’s true; it’s two versions behind (v0.24.0), but still looks good!

I’m loving that Cookbook on file uploads as well. It answered just this very thing: “where do files go when you upload them”

Thanks for this quick and thorough reply!

1 Like

Oh cool, thanks for this @Tobbe!

I had seen ImageKit, and thought about using it, but didn’t know how to integrate it with Redwood. Also, thought about simply using something like Netlify to serve all the content. Still, ImageKit seemed to have one of the best storage/ bandwidth policies. Most CDNs charge you for the bandwidth, while ImageKit, just charges you for the total storage with a generous 40 GB free!

Thanks for this response, and more validation on a way to get a working setup!

@lancelot I mentioned a few articles on building a blog, just to give you some ideas about such an app - not as a recommendation to use the tools presented in these articles. I doubt that you would find anything better than RWJS (I tried just about everything there is today :smile_cat: )

In the Recipes section there is a section called File Upload. I’m currently using that for my app, though I substituted Firebase for uploading.

Hey @lancelot, how did you get on using imagekit.io or cloudinary in combination with redwood.js out of curiosity? I’m in a similar situation, generally speaking, wanting to utilise free or low-cost quality services where I can for a small business website that is image asset-heavy and the idea of using AWS or FileStack isn’t ideal and almost makes me think Shopify, Squarespace, Webflow or WordPress might be better as the price point may be more predictable; I cringe as I’d rather not go in that direction however. I planned on this project being a crowning jewel for my student dev portfolio. Sorry, overshare. Love to know you got on though.

Hi @gracemorganmaxwell ! I’ve been using Filestack for all of my image stuff lately because they have an okay free tier (500 uploads/month, but only 1GB of bandwidth) which is probably okay for a portfolio? Depending on whether it makes Hacker News you might go over that 1GB pretty quick :sweat_smile:

Out of curiosity, how come you’re looking to avoid Filestack specifically? I’ve used Cloudinary in the past, but they got really expensive when you have a ton of files (when I left my last company I think the bill was $3,000/month :grimacing:)

I wrote up a how-to guide on the site for Filestack: File Uploads | RedwoodJS Docs That uses their upload widget, but you can use a plain ol <input type="file" /> if you want, it’s a couple lines of JS to actually upload a file to them and get the URL back:

const filestackClient = filestack.init(process.env.FILESTACK_API_KEY)

const upload = (event) => {
  const { url } = await filestackClient.upload(event.target.files[0])
}

// in your component
<input type="file" onChange={upload} />

I’d do some styling around the file input, it’s pretty ugly by default.

But if you really wanna get crazy, what’s your hosting situation? If you’re hosting somewhere that actually provides access/storage to save things to the filesystem (like an EC2 instance in AWS), you could create a RW function that’s available at a URL, and upload your files to that. Then, the function saves them to the local file system in a location that’s accessible by the web server, and they can be served like any other file in your codebase (this is how we used to do it in the good old days!).