Gatsby LightGallery Cloudinary

Written by Donald Boulton

PubliusLogic Repo
Sep 17, 20194 min readCloudinary, LightGallery  Category:  tech

Cloudinary React Library

🔗 Cloudinary React Library

🖼️ Cloudinary is a cloud service that offers a solution to a web application's entire image management pipeline.

Easily upload images to the cloud. Automatically perform smart image resizing, cropping and conversion without installing any complex software. Integrate Facebook or Twitter profile image extraction in a snap, in any dimension and style to match your website’s graphics requirements. Images are seamlessly delivered through a fast CDN, and much much more.

Cloudinary offers comprehensive APIs and administration capabilities and is easy to integrate with any web application, existing or new.

Cloudinary provides URL and HTTP based APIs that can be easily integrated with any Web development framework.

I have used 🔗 LightGalley in my ASP.NET, Core-2, Jekyll, React and now in my Gatsby site for Image Galleries and iframes to display any kind of html content.

This demo is using Styled Components and mediaQuery in a Styled CSS Grid for the image Cells.

LightGallery has a react SDK for usage in react and vanilla.js for the plugins. The jQuery plugins do not include the .js. as the code blocks below indicate.

LightGallery plugins

import 'lg-autoplay'
import 'lg-autoplay.js'
/* eslint-disable indent */
import React, { Component, Fragment } from 'react'
import { LightgalleryProvider, LightgalleryItem } from 'react-lightgallery'
import axios from 'axios'
import styled from 'styled-components'
import { CloudinaryContext, Transformation, Image } from 'cloudinary-react'
import { Grid, Cell } from 'styled-css-grid'
import { media } from '../../utils/mediaQuery'
import 'lightgallery.js/dist/css/lightgallery.css'

const SectionTitle = styled.h3`
  font-size: 1em;
  margin: 0.67em 0;
    font-size: .85em;
class Gallery extends Component {
  constructor (props) {
    super(props) = React.createRef()
    this.state = {
      gallery: [],
      isOpen: false,
      link: this.href,

  componentDidMount () {
    // Request for images tagged cats

      .then(res => {
        this.setState({ gallery: })
  onLink (event) {
    this.setState({ link: this.href = `

    image/upload/${data.public_id}.jpg` })
  uploadWidget () {
    let _this = this
    // eslint-disable-next-line no-undef
    cloudinary.openUploadWidget({ cloud_name: 'mansbooks', upload_preset:

    'photos-preset', tags: ['cats'], sources: ['local', 'url', 'camera',

    'image_search', 'facebook', 'dropbox', 'instagram'], dropboxAppKey:

    'YOUR KEY', googleApiKey: 'YOUR KEY' },
      // eslint-disable-next-line handle-callback-err
      function (error, result) {
      // Update gallery state with newly uploaded image
          _this.setState({ gallery: })
  render () { 
    return (
          <SectionTitle>Cloudinary LightGallery</SectionTitle>
            <CloudinaryContext cloudName='mansbooks'>
              <Grid columns='repeat(auto-fit,minmax(260px,1fr))' id='hash'>
       => {
                return (
                  <Cell key={data.public_id}>
                    <LightgalleryItem group='group1' src={`


                      <Image publicId={data.public_id} onClick={() =>

                      this.setState({ isOpen: true })}>
                      <div data-sub-html='public_id' />

export default Gallery

Upload Widget

The upload widget uses Cloudinary CND or the scripts, not a node module.

The Upload Widget Code with advanced styling

import React, { Component } from 'react'
import Helmet from 'react-helmet'
class UploadWidget extends Component {
  uploadWidget () {
      cloud_name: 'mansbooks',
      api_key: 'YOUR KEY',
      api_secret: 'YOUR SECRET',
      username: '',
      upload_preset: 'photos-preset',
      tags: ['cats', 'uploads'],
      sources: ['local', 'url', 'camera', 'image_search', 'facebook', 'dropbox', 'instagram'],
      dropboxAppKey: 'ADD YOUR DROPBOX APP KEY',
      googleApiKey: 'ADD YOUR API KEY',
      showAdvancedOptions: true,
      cropping: true,
      multiple: true,
      image_metadata: 'true',
      defaultSource: 'local',
      styles: {
        palette: {
          window: '#1D1D1D',
          sourceBg: '#000000',
          windowBorder: '#434040',
          tabIcon: '#FFFFFF',
          inactiveTabIcon: '#8E9FBF',
          menuIcons: '#D64000',
          link: '#D64000',
          action: '#9C3204',
          inProgress: '#D64000',
          complete: '#33ff00',
          error: '#EA2727',
          textDark: '#000000',
          textLight: '#FFFFFF',

    function (error, result) {
  render () {
    return (
      <div className='main'>
          <script src='' type='text/javascript' />
        <div className='upload'>
          <button onClick={this.uploadWidget.bind(this)} className='upload-button button'>
            Add Image

export default UploadWidget

Screen mediaQuery

This use's matchMedia for screen according to window size

import { startCase } from 'lodash'

const min = width => `only screen and (min-width: ${width}em)`
const max = width => `only screen and (max-width: ${width}em)`

const mediaQuery = {
  screens: {
    phone: 30,
    phablet: 40,
    tablet: 50,
    netbook: 60,
    laptop: 70,
    desktop: 100,

for (const key of Object.keys(mediaQuery.screens)) {
  const Key = startCase(key)
  for (const [func, name] of [[min, `min`], [max, `max`]]) {
    // css query
    const query = func(mediaQuery.screens[key])
    mediaQuery[name + Key] = `@media ` + query
    // js query (see window.matchMedia)
    mediaQuery[name + Key + `Js`] = query

export default mediaQuery

Rating: - Reviews
Is this a useful post? Please give us a rating!
Is this post Cool? Please Tweet About it!



    Page Contents


    Heatmaps by Hotjar

    Hotjar is the fast and visual way to understand your users..