Skip to content

add cloudinary image upload support #428

Open
rugeli wants to merge 14 commits intomainfrom
gallery
Open

add cloudinary image upload support #428
rugeli wants to merge 14 commits intomainfrom
gallery

Conversation

@rugeli
Copy link
Copy Markdown
Collaborator

@rugeli rugeli commented Apr 7, 2026

Problem

What is the problem this work solves, including
step 1 of #88

Solution

What I/we did to solve this problem

  • added a custom widget that opens the cloudinary upload widget , auto-derives upload folders from the cms entry.
    • one folder per cell line, e.g. cell-lines/AICS-{id}-{clone}
    • on successful upload, the widget stores the cloudinary img url into markdown frontmatter image field
  • created a shared component ImageRenderer to handle both gastby images(GatsbyImage) and external urls (<img>)
  • added image_url field via createResolvers in gatsby-node.js.
    • for a local image, image resolves to GatsbyImage, image_url is null
    • for cloudinary image urls, image is null and image_url carries the url

Notes:
This is mainly to show how Cloudinary can work with our current image management. With this change, images can now be uploaded to Cloudinary, while local images rendering still works the same as it does on main.

Things we can decide separately later:

  • whether porting the existing local images in this repo to cloud storage
  • in idea-board, implement a similar upload flow if we want to move forward with cloud image storage

Not yet implemented:

  • removing images from Cloudinary folders, except through the Cloudinary UI

Type of change

Please delete options that are not relevant.

  • New feature (non-breaking change which adds functionality)

Steps to Verify:

  1. on admin page, edit a cell line entry and use the new image upload widget
  2. cloudinary upload widget should open and upload to the correct folder, link to gallery (lmk if you have any issues opening or viewing)
  3. all images on the site should be rendered

Screenshots (optional):

Show-n-tell images/animations here

  • in Cloudinary, images are stored in designated folder structure
Screenshot 2026-04-07 at 2 51 54 PM
  • on the admin page, users can upload images to the cell line folder in Cloudinary. Local image preview remains unchanged.
Screenshot 2026-04-07 at 2 59 36 PM
  • but if clicks on Replace Image for a local image, the replacement image is uploaded to Cloudinary instead.
Screenshot 2026-04-07 at 3 22 51 PM

@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 7, 2026

Deploy Preview for cell-catalog ready!

Name Link
🔨 Latest commit 6f09b16
🔍 Latest deploy log https://app.netlify.com/projects/cell-catalog/deploys/69f1308d95a84900087b4bf0
😎 Deploy Preview https://deploy-preview-428--cell-catalog.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@rugeli rugeli marked this pull request as ready for review April 20, 2026 21:34
@rugeli rugeli requested a review from Copilot April 20, 2026 21:34
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Cloudinary-backed image uploads to the Decap CMS admin flow while preserving existing local-image rendering by introducing a dual image model (Gatsby image data vs external URL) and plumbing that URL through Gatsby GraphQL.

Changes:

  • Added a custom Decap CMS widget (cloudinary-image) that uploads to Cloudinary and writes the resulting URL into frontmatter.
  • Introduced ImageRenderer + ImageSource to render either GatsbyImage data or external <img src=...> URLs, and updated consumers accordingly.
  • Added an image_url GraphQL field (via createResolvers) and updated relevant queries to fetch it alongside existing image fields.

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
static/admin/config.yml Switches image widgets to the new cloudinary-image widget (including header background).
src/utils/mediaUtils.ts Adds isExternalUrl, updates image unpacking to support image_url, and changes thumbnail extraction to return ImageSource.
src/templates/disease-cell-line.tsx Queries image_url alongside existing image fields.
src/templates/cell-line.tsx Queries image_url alongside existing image fields (including media + diagrams + rnaseq).
src/style/images-and-videos.module.css Adjusts media container height styling.
src/components/shared/ImageRenderer.tsx New shared renderer for Gatsby images vs external URLs.
src/components/shared/DiagramCard.tsx Uses ImageRenderer and updates prop typing to accept ImageSource.
src/components/Thumbnail.tsx Uses ImageRenderer and updates prop typing to accept ImageSource.
src/components/SubPage/convert-data.ts Uses unpackImageData to normalize images into ImageSource.
src/components/ParentalLineModal.tsx Updates thumbnail rendering to support ImageSource via ImageRenderer.
src/components/ImagesAndVideo/MediaCard.tsx Replaces direct GatsbyImage usage with ImageRenderer.
src/components/ImagesAndVideo/ImagePreviewGroup.tsx Supports previewing external URLs by bypassing getSrc when needed.
src/components/CellLineTable/SharedColumns.tsx Updates thumbnail rendering logic to support external URLs.
src/component-queries/types.ts Introduces ImageSource and updates frontmatter/result types for Cloudinary URL support.
src/component-queries/NormalCellLines.tsx Adds image_url to the table query.
src/component-queries/DiseaseCellLines.tsx Adds image_url to the disease table query.
src/cms/widgets/CloudinaryImageWidget.tsx New Cloudinary upload widget implementation (script loading, folder derivation, preview).
src/cms/cms.tsx Registers the custom cloudinary-image widget with Decap CMS.
src/cms/cloudinaryConfig.ts Adds Cloudinary widget configuration constants.
gatsby-node.js Adds schema/types/resolvers for image_url and introduces an ImagesAndVideos type.
Comments suppressed due to low confidence (1)

gatsby-node.js:68

  • ImagesAndVideos is now explicitly typed but only includes images. Existing GraphQL queries in src/templates/cell-line.tsx request images_and_videos { videos { ... } }, so this schema will either drop the videos field or rely on inference (which is brittle) and can break builds. Define a VideoWithCaption type and add videos: [VideoWithCaption] to ImagesAndVideos (or otherwise include the videos field explicitly) so the schema matches frontmatter usage.
        ` type ImgWithCaption {
            image: File @fileByRelativePath
            caption: String
            }
            type ImagesAndVideos {
            images: [ImgWithCaption]
            }
            type Diagram {
            title: String
            images: [ImgWithCaption]
            }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/cms/widgets/CloudinaryImageWidget.tsx
Comment thread src/cms/cloudinaryConfig.ts
Comment thread static/admin/config.yml
Comment thread src/cms/widgets/CloudinaryImageWidget.tsx
Comment thread src/cms/widgets/CloudinaryImageWidget.tsx
@rugeli rugeli requested review from interim17 and meganrm May 1, 2026 21:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants