{"id":21642,"date":"2018-02-28T19:21:28","date_gmt":"2018-02-28T19:21:28","guid":{"rendered":"http:\/\/cloudinary_image_gallery_with_stencil_custom_components"},"modified":"2024-06-05T15:56:21","modified_gmt":"2024-06-05T22:56:21","slug":"cloudinary_image_gallery_with_stencil_custom_components","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components","title":{"rendered":"Cloudinary Image Gallery With Stencil Custom Components"},"content":{"rendered":"<div class=\"wp-block-cloudinary-markdown \"><p>When you need to build small custom web components that can be used across all frameworks &#8211; Angular, React, Vue vanilla JS and others &#8211; Stencil is an ideal tool. Stencil enables you to create platform-independent components that can be exported as a true web component and used anywhere.<\/p>\n<p>Check out our StencilJS Posts:<\/p>\n<ul>\n<li>\n<a href=\"https:\/\/cloudinary.com\/blog\/getting_started_with_stenciljs\">Getting Started with StencilJS<\/a>\n<\/li>\n<li>\n<a href=\"https:\/\/blog.ionicframework.com\/make-a-video-web-component-the-stencil-way\/\">Make a Video Web Component, the Stencil Way<\/a>\n<\/li>\n<\/ul>\n<p>This article shows how to build an image gallery with Cloudinary-stored images using Stencil. <a href=\"https:\/\/cloudinary.com\/\">Cloudinary<\/a> is an end-to-end image and video management solution. The Cloudinary <a href=\"https:\/\/cloudinary.com\/image-api\">Image API<\/a> is very easy to use and exposes image transformation techniques via HTTP URLs. If you have never used Stencil, you can get started with <a href=\"https:\/\/cloudinary.com\/blog\/getting_started_with_stenciljs\">this article<\/a>.<\/p>\n<h2>Setup a Media Library and a Stencil Project<\/h2>\n<p>Let\u2019s start with uploading some images to the Cloudinary server and setting up a Stencil project.<\/p>\n<h3>Create a Cloudinary Account<\/h3>\n<p>We will upload images using the Cloudinary dashboard. In real projects, however, you should have a server that uses the Cloudinary SDK to upload these images.<\/p>\n<ol>\n<li>Create a Cloudinary account by signing up for the <a href=\"https:\/\/cloudinary.com\/users\/register\/free\">free plan, offering 300,000 images<\/a>.\n<img decoding=\"async\" src=\"https:\/\/cloudinary-res.cloudinary.com\/image\/upload\/w_700,c_fill\/dpr_auto\/Screen_Shot_2017-09-25_at_7.45.41_AM_eejr9q.png\" alt=\"Cloudinary Sign Up\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1400\" height=\"1022\"\/>\n<\/li>\n<li>On your server dashboard\/console, click on Media Library in the navigation bar.<\/li>\n<li>Use the image upload widget on the Media Library page to add images to your server.\n<img decoding=\"async\" src=\"https:\/\/cloudinary-res.cloudinary.com\/image\/upload\/w_700,c_fill\/dpr_auto\/Screen_Shot_2017-09-25_at_7.48.23_AM_rhdpai.png\" alt=\"Cloudinary Media Library\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1400\" height=\"831\"\/>\n<\/li>\n<\/ol>\n<h3>Create a Stencil Project<\/h3>\n<p>The first thing we need to do with Stencil is to set up a boilerplate for a Stencil project. Fortunately, the <a href=\"https:\/\/ionicframework.com\/\">Ionic<\/a> team provides a starter template to simplify this setup process. All  you need to do is clone this starter template, install the template and start your new project:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\"><span class=\"hljs-comment\"># Clone<\/span>\ngit <span class=\"hljs-keyword\">clone<\/span> https:<span class=\"hljs-comment\">\/\/github.com\/ionic-team\/stencil-starter.git cl-gallery<\/span>\n\n<span class=\"hljs-comment\"># Enter project<\/span>\ncd cl-gallery\n\n<span class=\"hljs-comment\"># Remove original Github history<\/span>\ngit remote rm origin\n\n<span class=\"hljs-comment\"># Install dependencies<\/span>\nnpm install\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<h2>Create a Gallery Data Source<\/h2>\n<p>A typical gallery app or widget requires a data source. Most real situations would probably require fetching these data from a server or an API endpoint. There is no need for that in this app. We are going to create a mock data that looks like what a server would send to us.<\/p>\n<p>Create <code>db.ts<\/code> in your <code>src<\/code> directory with the following content:<\/p>\n<p><strong>Full code available <a href=\"https:\/\/gist.github.com\/Maharony\/257976fd5087047a31ea703f9db3c7e5\">HERE<\/a><\/strong><\/p>\n<p>Just an export of an array of gallery images. Each gallery item is represented as an object with an image ID, collector\/author and description about the image. The image ID (<code>imageId<\/code>) is the same ID you get when you upload an image to Cloudinary server. We can use the these IDs to fetch the images from Cloudinary.<\/p>\n<h2>Deliver and Transform Images with Cloudinary SDK<\/h2>\n<p>The browser will not understand an image ID. We need to use the Cloudinary SDK to convert image IDs to URLs. This process is known as \u201cdelivery.\u201d<\/p>\n<p>We also need to define a width and quality attribute for  the image. This process is done with the SDK and referred to as \u201ctransformation.\u201d<\/p>\n<p>Before we dive into these, let\u2019s first create a container component to serve as our app shell and interact with Cloudinary. Create a folder <code>site<\/code> in the <code>components<\/code> directory with the following contents:<\/p>\n<ul>\n<li>app-site.scss<\/li>\n<li>app-site.tsx<\/li>\n<\/ul>\n<p>Then update the<code> app-site.tsx<\/code> file with the following content:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">import<\/span> { Component } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@stencil\/core'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> cloudinary <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'cloudinary-core'<\/span>;\n<span class=\"hljs-keyword\">import<\/span> data <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'..\/..\/db'<\/span>;\n\n@Component({\n  <span class=\"hljs-attr\">tag<\/span>: <span class=\"hljs-string\">'app-site'<\/span>,\n  <span class=\"hljs-attr\">styleUrl<\/span>: <span class=\"hljs-string\">'app-site.scss'<\/span>\n})\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Site<\/span> <\/span>{\n\n  cloudinary = <span class=\"hljs-literal\">null<\/span>;\n  galleryImages = &#91;];\n\n  componentWillLoad() {\n    <span class=\"hljs-keyword\">this<\/span>.cloudinary = cloudinary.Cloudinary.new({\n      <span class=\"hljs-attr\">cloud_name<\/span>: <span class=\"hljs-string\">''<\/span>\n    })\n    <span class=\"hljs-keyword\">this<\/span>.galleryImages = data.map(<span class=\"hljs-keyword\">this<\/span>.transform.bind(<span class=\"hljs-keyword\">this<\/span>));\n  }\n\n  transform(image) {\n    <span class=\"hljs-keyword\">const<\/span> imageUrl =\n      <span class=\"hljs-keyword\">this<\/span>.cloudinary.url(image.imageId, { <span class=\"hljs-attr\">width<\/span>: <span class=\"hljs-number\">300<\/span>, <span class=\"hljs-attr\">crop<\/span>: <span class=\"hljs-string\">\"fit\"<\/span>, <span class=\"hljs-attr\">quality<\/span>: <span class=\"hljs-string\">'auto'<\/span>, <span class=\"hljs-attr\">secure<\/span>: <span class=\"hljs-literal\">true<\/span> });\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-built_in\">Object<\/span>.assign(image, { imageUrl });\n  }\n\n  render() {\n    <span class=\"hljs-keyword\">return<\/span> (\n      <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"wrapper\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">nav<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>CL Gallery<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">nav<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"gallery-images\"<\/span>&gt;<\/span>\n          {this.galleryImages.map(image =&gt; \n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">cl-gallery-item<\/span> <span class=\"hljs-attr\">image<\/span>=<span class=\"hljs-string\">{image}<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">cl-gallery-item<\/span>&gt;<\/span>\n          )}\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n    );\n  }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<ul>\n<li>Stencil looks very much like React because it uses JSX and has a resemblance in syntax. A component is defined as a class, but it is decorated with the <code>Component<\/code> decorator that we imported from the <code>Stencil<\/code> core above. The <code>tag<\/code> in the decorator is what is used to mount this component in a containing template, while the <code>styleUrl<\/code> is the SCSS file that defines the component\u2019s styles.<\/li>\n<li>The class has two properties, <code>cloudinary<\/code> and <code>galleryImages<\/code>. <code>cloudinary<\/code> is going to keep a reference to the configured Cloudinary instance. This configuration happens when the component is about to be mounted in <code>componentWillLoad<\/code>. <code>galleryImages<\/code> keeps references to the array of images from our data source.<\/li>\n<li>\n<code>componentWillLoad<\/code> is executed before component loads, so we are setting up Cloudinary and our data store before the component is rendered. To configure Cloudinary, pass in the cloud name from your Cloudinary server.<\/li>\n<li>The data store is transformed before being passed to <code>galleryImages<\/code>. It\u2019s transformed with a <code>transform<\/code> method, which generates a URL and transforms the image using the object passed as second argument.<\/li>\n<li>Finally, we use JSX to render a child component, <code>cl-gallery-item<\/code> that receives each item from the <code>galleryImages<\/code> via props.<\/li>\n<\/ul>\n<h2>Rendering Images with Child Component<\/h2>\n<p>Create another component folder, <code>cl-gallery-item<\/code> with the following files:<\/p>\n<ul>\n<li>cl-gallery-item.scss<\/li>\n<li>cl-gallery-item.tsx<\/li>\n<\/ul>\n<p>The following logic should be in your TSX file:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">import<\/span> { Component, Prop } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@stencil\/core'<\/span>;\n\n\n@Component({\n  <span class=\"hljs-attr\">tag<\/span>: <span class=\"hljs-string\">'cl-gallery-item'<\/span>,\n  <span class=\"hljs-attr\">styleUrl<\/span>: <span class=\"hljs-string\">'cl-gallery-item.scss'<\/span>\n})\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ClGalleryItem<\/span> <\/span>{\n\n  @Prop() image: any;\n\n  render() {\n    <span class=\"hljs-keyword\">return<\/span> (\n      <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"cl-gallery-item\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{this.image.imageUrl}<\/span> <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">\"\"<\/span>\/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h3<\/span>&gt;<\/span>{this.image.collector}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h3<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>{this.image.description}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n    );\n  }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>The only change here is that we decorate a property with <code>Prop<\/code>. This property is called image and maps to the property that was passed to this component from the parent component, <code>app-site.tsx<\/code>. The property holds a gallery item, which we can then display using JSX.<\/p>\n<h2>Update App\u2019s Entry Point<\/h2>\n<p>Originally, this project has one component, which is the default component. The component is named <code>my-name<\/code>. Open <code>index.html<\/code> and you will see it\u2019s right there, so even if you keep running the app with all these changes, the visuals will never update.<\/p>\n<p>Update the <code>index.html<\/code> and replace <code>my-name<\/code> component with <code>app-site<\/code> and we are good to go:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">html<\/span> <span class=\"hljs-attr\">dir<\/span>=<span class=\"hljs-string\">\"ltr\"<\/span> <span class=\"hljs-attr\">lang<\/span>=<span class=\"hljs-string\">\"en\"<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">head<\/span>&gt;<\/span>\n ...\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">head<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n  \n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">app-site<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">app-site<\/span>&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">body<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">html<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Run the following command to see the app running at port 3333:<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">npm start\n<\/code><\/span><\/pre>\n<p>You should see a simple grid like the one shown below:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-res.cloudinary.com\/image\/upload\/w_700,c_fill\/dpr_auto\/Screen_Shot_2017-09-30_at_10.39.04_PM_piernf.png\" alt=\"Stencil final example\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1400\" height=\"889\"\/><\/p>\n<p>Feel free to check out the <a href=\"https:\/\/github.com\/christiannwamba\/cl-gallery-stencil\">code on GitHub<\/a>.<\/p>\n<h2>Conclusion<\/h2>\n<p>Stencil is quite promising and it stands out because of its ability to <a href=\"https:\/\/stenciljs.com\/docs\/distribution\">export components<\/a> that are compatible with any other JavaScript environment. It enables you to write light components for widgets, like a Cloudinary Gallery; export the components; and import them in your Angular, React or Vue project. Cloudinary offers more than what we just discussed, including <a href=\"https:\/\/cloudinary.com\/blog\/automating_file_upload_and_sharing\">file upload<\/a>, <a href=\"https:\/\/cloudinary.com\/documentation\/transformation_reference\">image manipulation<\/a>, <a href=\"https:\/\/cloudinary.com\/documentation\/image_optimization\">image optimization<\/a>, and more. You can learn about all these <a href=\"https:\/\/cloudinary.com\/products\/image_video_technology_platform\">features<\/a> or <a href=\"https:\/\/cloudinary.com\/users\/register\/free\">get started for free<\/a>.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":41,"featured_media":21643,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[134,165,227],"class_list":["post-21642","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-guest-post","tag-image-transformation","tag-performance-optimization"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.6 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Cloudinary Image Gallery With Stencil Custom Components<\/title>\n<meta name=\"description\" content=\"Learn how to build an image gallery with Cloudinary-stored images using Stencil.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Cloudinary Image Gallery With Stencil Custom Components\" \/>\n<meta property=\"og:description\" content=\"Learn how to build an image gallery with Cloudinary-stored images using Stencil.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2018-02-28T19:21:28+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-06-05T22:56:21+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1649723542\/Web_Assets\/blog\/StecilJS_Image_Gallery\/StecilJS_Image_Gallery-png?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"1540\" \/>\n\t<meta property=\"og:image:height\" content=\"847\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"NewsArticle\",\"@id\":\"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Cloudinary Image Gallery With Stencil Custom Components\",\"datePublished\":\"2018-02-28T19:21:28+00:00\",\"dateModified\":\"2024-06-05T22:56:21+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components\"},\"wordCount\":7,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649723542\/Web_Assets\/blog\/StecilJS_Image_Gallery\/StecilJS_Image_Gallery.png?_i=AA\",\"keywords\":[\"Guest Post\",\"Image Transformation\",\"Performance Optimization\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2018\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components\",\"url\":\"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components\",\"name\":\"Cloudinary Image Gallery With Stencil Custom Components\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649723542\/Web_Assets\/blog\/StecilJS_Image_Gallery\/StecilJS_Image_Gallery.png?_i=AA\",\"datePublished\":\"2018-02-28T19:21:28+00:00\",\"dateModified\":\"2024-06-05T22:56:21+00:00\",\"description\":\"Learn how to build an image gallery with Cloudinary-stored images using Stencil.\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649723542\/Web_Assets\/blog\/StecilJS_Image_Gallery\/StecilJS_Image_Gallery.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649723542\/Web_Assets\/blog\/StecilJS_Image_Gallery\/StecilJS_Image_Gallery.png?_i=AA\",\"width\":1540,\"height\":847},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Cloudinary Image Gallery With Stencil Custom Components\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"name\":\"Cloudinary Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudinary.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\",\"name\":\"Cloudinary Blog\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"width\":312,\"height\":60,\"caption\":\"Cloudinary Blog\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Cloudinary Image Gallery With Stencil Custom Components","description":"Learn how to build an image gallery with Cloudinary-stored images using Stencil.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components","og_locale":"en_US","og_type":"article","og_title":"Cloudinary Image Gallery With Stencil Custom Components","og_description":"Learn how to build an image gallery with Cloudinary-stored images using Stencil.","og_url":"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components","og_site_name":"Cloudinary Blog","article_published_time":"2018-02-28T19:21:28+00:00","article_modified_time":"2024-06-05T22:56:21+00:00","og_image":[{"width":1540,"height":847,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1649723542\/Web_Assets\/blog\/StecilJS_Image_Gallery\/StecilJS_Image_Gallery-png?_i=AA","type":"image\/png"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components"},"author":{"name":"","@id":""},"headline":"Cloudinary Image Gallery With Stencil Custom Components","datePublished":"2018-02-28T19:21:28+00:00","dateModified":"2024-06-05T22:56:21+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components"},"wordCount":7,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649723542\/Web_Assets\/blog\/StecilJS_Image_Gallery\/StecilJS_Image_Gallery.png?_i=AA","keywords":["Guest Post","Image Transformation","Performance Optimization"],"inLanguage":"en-US","copyrightYear":"2018","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components","url":"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components","name":"Cloudinary Image Gallery With Stencil Custom Components","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649723542\/Web_Assets\/blog\/StecilJS_Image_Gallery\/StecilJS_Image_Gallery.png?_i=AA","datePublished":"2018-02-28T19:21:28+00:00","dateModified":"2024-06-05T22:56:21+00:00","description":"Learn how to build an image gallery with Cloudinary-stored images using Stencil.","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649723542\/Web_Assets\/blog\/StecilJS_Image_Gallery\/StecilJS_Image_Gallery.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649723542\/Web_Assets\/blog\/StecilJS_Image_Gallery\/StecilJS_Image_Gallery.png?_i=AA","width":1540,"height":847},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/cloudinary_image_gallery_with_stencil_custom_components#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Cloudinary Image Gallery With Stencil Custom Components"}]},{"@type":"WebSite","@id":"https:\/\/cloudinary.com\/blog\/#website","url":"https:\/\/cloudinary.com\/blog\/","name":"Cloudinary Blog","description":"","publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudinary.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cloudinary.com\/blog\/#organization","name":"Cloudinary Blog","url":"https:\/\/cloudinary.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","width":312,"height":60,"caption":"Cloudinary Blog"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":""}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649723542\/Web_Assets\/blog\/StecilJS_Image_Gallery\/StecilJS_Image_Gallery.png?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/21642","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=21642"}],"version-history":[{"count":5,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/21642\/revisions"}],"predecessor-version":[{"id":34423,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/21642\/revisions\/34423"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/21643"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=21642"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=21642"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=21642"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}