{"id":28518,"date":"2022-04-06T02:45:03","date_gmt":"2022-04-06T02:45:03","guid":{"rendered":"http:\/\/Build-an-e-commerce-product-customization-page-in-Nuxt.js"},"modified":"2022-04-06T02:45:03","modified_gmt":"2022-04-06T02:45:03","slug":"build-an-e-commerce-product-customization-page-in-nuxt-js","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/","title":{"rendered":"E-commerce product customization page in NuxtJS"},"content":{"rendered":"<div class=\"wp-block-cloudinary-markdown \"><p>One of the super-powers of modern e-commerce applications is a meaningful user experience that allows customers to demand tailor-made products and the flexibility to customize such products.<\/p>\n<p>This post will discuss how to build a customizable product component using <a href=\"https:\/\/nuxtjs.org\/\">Nuxt.js<\/a> and <a href=\"https:\/\/cloudinary.com\/\">Cloudinary<\/a>. At the end of this tutorial, we will learn how to use Cloudinary robust transformation properties to enhance product customization and experience.<\/p>\n<p>Nuxt.js is a vue-based frontend development framework that enables functionalities like server-side rendering, static site generation, file-system routing, components auto-import, and API endpoints for backend features.<\/p>\n<p>Cloudinary is a visual media service we use to upload, store, manage, transform, and deliver images and videos for websites and applications. The platform also offers a vast collection of software development kits (SDKs) for frontend frameworks and libraries.<\/p>\n<h2>Sandbox<\/h2>\n<p>We completed this project in <a href=\"https:\/\/codesandbox.io\/s\/divine-surf-2qw59\">a CodeSan<\/a><a href=\"https:\/\/codesandbox.io\/s\/divine-surf-2qw59\">d<\/a><a href=\"https:\/\/codesandbox.io\/s\/divine-surf-2qw59\">box<\/a>, and you can fork it to run the code.<\/p>\n<\/div>\n  \n  <div class=\"wp-block-cloudinary-code-sandbox \">\n    <iframe\n      src=\"https:\/\/codesandbox.io\/embed\/divine-surf-2qw59?theme=dark&amp;codemirror=1&amp;highlights=&amp;editorsize=50&amp;fontsize=14&amp;expanddevtools=0&amp;hidedevtools=0&amp;eslint=0&amp;forcerefresh=0&amp;hidenavigation=0&amp;initialpath=%2F&amp;module=&amp;moduleview=0&amp;previewwindow=&amp;view=&amp;runonclick=1\"\n      height=\"500\"\n      style=\"width: 100%;\"\n      title=\"ecommerce product customization page in nuxtjs\"\n      loading=\"lazy\"\n      allow=\"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking\"\n      sandbox=\"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts\"\n    ><\/iframe>\n  <\/div>\n\n  <div class=\"wp-block-cloudinary-markdown \"><p>Github link <a href=\"https:\/\/github.com\/Mr-Malomz\/e_corm_product\">here<\/a>.<\/p>\n<h2>Prerequisites<\/h2>\n<p>The following steps in this post require JavaScript and Vue.js experience. Experience with Nuxt.js isn\u2019t a requirement, but it\u2019s nice to have.<\/p>\n<p>We also need a <a href=\"https:\/\/cloudinary.com\/\">Cloudinary account<\/a> to store and transform media assets. <a href=\"https:\/\/cloudinary.com\/users\/register\/free\"><strong>Signup<\/strong><\/a> <strong>is completely free<\/strong>.<\/p>\n<h2>Getting Started<\/h2>\n<p>We need to create a Nuxt.js starter project by navigating to the desired directory and running the command below in our terminal.<\/p>\n<pre class=\"js-syntax-highlighted\"><code>    npx create-nuxt-app e_corm_product &amp;&amp; cd e_corm_product\n<\/code><\/pre>\n<p>This command will ask us some questions on how to configure our application. We can answer the questions as shown below:<\/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\">Ok to proceed? (y) &lt; PRESS <span class=\"hljs-string\">\"y\"<\/span> <span class=\"hljs-keyword\">and<\/span> hit ENTER&gt;\nproject name: &lt;PRESS ENTER&gt;\nprogramming langauge: &lt;JAVASCRIPT&gt;\npackage manager: &lt;NPM&gt;\nUI framework: &lt;TAILWIND CSS&gt;\nNuxt.js modules: &lt;AXIOS - PROMISE BASED HTTP CLIENT&gt;\nLinting tools: &lt;ESLINT, PRETTIER&gt;\nTesting framework: &lt;NONE&gt;\nRendering mode: &lt;UNIVERSAL (SSR\/<span class=\"hljs-keyword\">STATIC<\/span>)\n Deployment target: &lt;<span class=\"hljs-keyword\">STATIC<\/span>\/JAMSTACK HOSTING&gt;\n Deployment tools: &lt;JSCONFIG.JSON&gt;\n Continous integration: &lt;NONE&gt;\n Version control system: &lt;GIT&gt;\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<p>The command creates a Nuxt.js project with TailwindCSS called <code>e_corm_product<\/code>, and navigates into the project directory.<\/p>\n<p><a href=\"https:\/\/tailwindcss.com\/\">TailwindCSS<\/a> is a utility-first CSS framework packed with classes to help us style our web page.<\/p>\n<p>We proceed to install the <a href=\"https:\/\/cloudinary.nuxtjs.org\/\">@nuxtjs\/cloudinary<\/a> dependency with:<\/p>\n<pre><code>npm install @nuxtjs\/cloudinary\n<\/code><\/pre>\n<p><strong>Configuring Cloudinary in Nuxt.js<\/strong><\/p>\n<p>First, we need to modify the <code>nuxt.config.js<\/code> file by adding <code>@nuxtjs\/cloudinary<\/code> as a module in the  <code>modules<\/code> section:<\/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\">    modules: &#91;\n        <span class=\"hljs-string\">'@nuxtjs\/cloudinary'<\/span>, <span class=\"hljs-comment\">\/\/add this<\/span>\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<p>Next, we need to configure Cloudinary by adding a <code>cloudinary<\/code> section below the <code>modules<\/code> section as shown below:<\/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\">    modules: &#91;\n        <span class=\"hljs-string\">'@nuxtjs\/cloudinary'<\/span>,\n      ],\n    \n    <span class=\"hljs-comment\">\/\/add this<\/span>\n    <span class=\"hljs-attr\">cloudinary<\/span>: {\n        <span class=\"hljs-attr\">cloudName<\/span>: <span class=\"hljs-string\">'&lt;your-cloud-name&gt;'<\/span>,\n        <span class=\"hljs-attr\">useComponent<\/span>: <span class=\"hljs-literal\">true<\/span>,\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 <code>useComponent<\/code> flag set to <code>true<\/code> lets us use the built-in Cloudinary components. Our cloud name is obtained from our Cloudinary dashboard.<\/p>\n<h2>Image sourcing and upload to Cloudinary<\/h2>\n<p>Next, we need to upload sample images for products and overlays to create product customization.<\/p>\n<p><strong>Product Image<\/strong><\/p>\n<ul>\n<li>\n<a href=\"https:\/\/res.cloudinary.com\/dtgbzmpca\/image\/upload\/v1642329620\/Hanging_T-Shirt_v83je9.png\">https:\/\/res.cloudinary.com\/dtgbzmpca\/image\/upload\/v1642329620\/Hanging_T-Shirt_v83je9.png<\/a>\n<\/li>\n<\/ul>\n<p><strong>Overlay Images<\/strong><\/p>\n<ul>\n<li>\n<a href=\"https:\/\/res.cloudinary.com\/dtgbzmpca\/image\/upload\/v1642367747\/cloudinary-logo.jpg\">https:\/\/res.cloudinary.com\/dtgbzmpca\/image\/upload\/v1642367747\/cloudinary-logo.jpg<\/a>\n<\/li>\n<li>\n<a href=\"https:\/\/res.cloudinary.com\/dtgbzmpca\/image\/upload\/v1642367682\/fire.png\">https:\/\/res.cloudinary.com\/dtgbzmpca\/image\/upload\/v1642367682\/fire.png<\/a>\n<\/li>\n<\/ul>\n<p>In our Cloudinary dashboard, we uploaded the images by clicking on the <strong>Media Library<\/strong> tab, clicking on <strong>Upload<\/strong>, selecting <strong>Web Address<\/strong> option, input the <strong>url<\/strong>, and clicking on the <strong>Arrow Button<\/strong> to upload.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/media_jams\/s_09154C99BD025007588E7E863D13AB13FE936D0B55FA69EF06F32C362371F6D6_1635104341304_Screenshot+2021-10-24+at+20.37.46.png\" alt=\"Cloudinary console and upload button for other formats of upload\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"2000\" height=\"275\"\/><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/media_jams\/s_83F3FBD7ECC4D58C256BC95B11E26148AE441C8ED8A1FF0E7E7D0A2229B1C1FD_1642503859751_Screenshot+2022-01-16+at+22.15.17.png\" alt=\"select web address and enter url\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"2000\" height=\"958\"\/><\/p>\n<p>After uploading all the images, we will see them displayed on the console with their <code>publicId<\/code>. The <strong>ID<\/strong>s will come in handy when creating product customization.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/media_jams\/s_1B7DF603BF129553B0BB8EA1D660CB8B1B30DC300EAD4CB5AA11C010096263A1_1642910419573_Screenshot+2022-01-16+at+22.38.47.png\" alt=\"Uploaded image with publicId highlighted\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"2000\" height=\"958\"\/><\/p>\n<h2>Setup collection for our customization<\/h2>\n<p>Next, we need to create a <code>utils<\/code> folder in the project root directory. In this folder, we create <code>availableColors.json<\/code>, <code>fontList.json<\/code>, and <code>imageList.json<\/code>. These files contain data for colors, fonts, and images respectively.<\/p>\n<p>Here is the JSON data for each file.<\/p>\n<p><strong>availableColors.json<\/strong><\/p>\n<pre class=\"js-syntax-highlighted\"><code>    [&quot;FFFFFF&quot;, &quot;47E8D2&quot;, &quot;DCA381&quot;, &quot;702C3C&quot;, &quot;E9C660&quot;, &quot;A11D1F&quot;, &quot;897115&quot;, &quot;598DE6&quot;]\n<\/code><\/pre>\n<p><strong>fontList.json<\/strong><\/p>\n<pre class=\"js-syntax-highlighted\"><code>[\n   { &quot;title&quot;: &quot;Arial&quot;, &quot;value&quot;: &quot;Arial&quot; },\n   { &quot;title&quot;: &quot;Georgia&quot;, &quot;value&quot;: &quot;Georgia&quot; },\n   { &quot;title&quot;: &quot;Sacremento&quot;, &quot;value&quot;: &quot;Sacramento&quot; },\n   { &quot;title&quot;: &quot;Roboto&quot;, &quot;value&quot;: &quot;Roboto&quot; },\n   { &quot;title&quot;: &quot;Montserrat&quot;, &quot;value&quot;: &quot;Montserrat&quot; },\n   { &quot;title&quot;: &quot;Bitter&quot;, &quot;value&quot;: &quot;Bitter&quot; }\n]\n<\/code><\/pre>\n<p><strong>imageList.json<\/strong><\/p>\n<pre><code>[\n    {\n        &quot;id&quot;: 1,\n        &quot;publicId&quot;: &quot;&quot;\n    },\n    {\n        &quot;id&quot;: 2,\n        &quot;publicId&quot;: &quot;&lt;REPLACE THIS WITH YOUR OVERLAY IMAGE PUBLICID&gt;&quot;\n    },\n    {\n        &quot;id&quot;: 3,\n        &quot;publicId&quot;: &quot;&lt;REPLACE THIS WITH YOUR OVERLAY IMAGE PUBLICID&gt;&quot;\n    }\n]\n<\/code><\/pre>\n<p><strong>PS:<\/strong> <em>The first item\u2019s <code>**publicId**<\/code> is left empty because it serves as the default state when no overlay is required.<\/em><\/p>\n<h2>Product Customization with Cloudinary<\/h2>\n<p>Next, we need to create components that will serve as the building blocks of our application:<\/p>\n<ul>\n<li>\n<code>ColorPicker<\/code> a component for sets of predefined colors.<\/li>\n<li>\n<code>ColorDropPicker<\/code> a component for picking a custom colour for our product.<\/li>\n<li>\n<code>ImagePicker<\/code> a component for picking image.<\/li>\n<li>\n<code>TextCustomPicker<\/code> a component for selecting fonts and adding custom text.<\/li>\n<li>\n<code>ProductImage<\/code> a component for rendering customized product.<\/li>\n<\/ul>\n<p><strong>ColorPicker Component<\/strong>\nTo do this, we navigate to the <code>components<\/code> folder, and in this folder, create a <code>ColorPicker.vue<\/code> file containing the code snippet below:<\/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\">template<\/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\">\"w-full mb-6\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h4<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"mb-4 font-semibold\"<\/span>&gt;<\/span>Select a color:<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h4<\/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\">\"flex\"<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span>\n            <span class=\"hljs-attr\">v-for<\/span>=<span class=\"hljs-string\">\"(color, i) in availableColors\"<\/span>\n            <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"w-8 h-8 mr-2 block\"<\/span>\n            <span class=\"hljs-attr\">:class<\/span>=<span class=\"hljs-string\">\"&#91;\n              i === 0 ? 'border' : '',\n              selectedColor === color ? 'border-4 border-red-400' : '',\n            ]\"<\/span>\n            <span class=\"hljs-attr\">:key<\/span>=<span class=\"hljs-string\">\"i\"<\/span>\n            <span class=\"hljs-attr\">:style<\/span>=<span class=\"hljs-string\">\"{ background: `#${color}` }\"<\/span>\n            @<span class=\"hljs-attr\">click<\/span>=<span class=\"hljs-string\">\"setActiveColor(color)\"<\/span>\n          &gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\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>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">template<\/span>&gt;<\/span>\n    \n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span>&gt;<\/span><span class=\"javascript\">\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> {\n      <span class=\"hljs-attr\">props<\/span>: {\n        <span class=\"hljs-attr\">availableColors<\/span>: { <span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-built_in\">Array<\/span>, <span class=\"hljs-attr\">required<\/span>: <span class=\"hljs-literal\">true<\/span> },\n        <span class=\"hljs-attr\">setActiveColor<\/span>: { <span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-built_in\">Function<\/span>, <span class=\"hljs-attr\">required<\/span>: <span class=\"hljs-literal\">true<\/span> },\n        <span class=\"hljs-attr\">selectedColor<\/span>: { <span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-built_in\">String<\/span>, <span class=\"hljs-attr\">required<\/span>: <span class=\"hljs-literal\">true<\/span> },\n      },\n    }\n    <\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/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>The snippet above does the following:<\/p>\n<ul>\n<li>Configures the component to accept <code>availableColors<\/code>, <code>setActiveColor<\/code>, and <code>selectedColor<\/code> props.<\/li>\n<li>Markup shows the list of the available colours, sets the first item as active by default, and a click event to change the active colour.<\/li>\n<\/ul>\n<p><strong>ColorDropPicker Component<\/strong>\nIn the same  <code>components<\/code> folder, create a <code>ColorDropPicker.vue<\/code> file containing the code snippet below:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-5\" 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\">template<\/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\">\"w-full mb-6\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h4<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"mb-2 font-semibold\"<\/span>&gt;<\/span>Add a custom color:<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h4<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span>\n          <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"color\"<\/span>\n          <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"\"<\/span>\n          <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"\"<\/span>\n          <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"h-9 w-20 border-2 cursor-pointer\"<\/span>\n          @<span class=\"hljs-attr\">change<\/span>=<span class=\"hljs-string\">\"onChange\"<\/span>\n        \/&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">template<\/span>&gt;<\/span>\n    \n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span>&gt;<\/span><span class=\"javascript\">\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> {\n      <span class=\"hljs-attr\">props<\/span>: {\n        <span class=\"hljs-attr\">setActiveColor<\/span>: { <span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-built_in\">Function<\/span>, <span class=\"hljs-attr\">required<\/span>: <span class=\"hljs-literal\">true<\/span> },\n      },\n      <span class=\"hljs-attr\">methods<\/span>: {\n        onChange(event) {\n          <span class=\"hljs-keyword\">this<\/span>.setActiveColor(event.target.value.slice(<span class=\"hljs-number\">1<\/span>))\n        },\n      },\n    }\n    <\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><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>The snippet above does the following:<\/p>\n<ul>\n<li>Configures the component to accept  <code>setActiveColor<\/code> props.<\/li>\n<li>Creates an <code>onChange<\/code> method that uses the <code>sectActiveColor<\/code> props to change the colour. This method also removes the first letter from the generated colour. E.g., colour <code>#ffffff<\/code> will return as <code>ffffff<\/code>.<\/li>\n<li>Markup shows an input field of type <code>color<\/code>  and a <code>change<\/code> event to select a custom colour.<\/li>\n<\/ul>\n<p><strong>ImagePicker Component<\/strong>\nIn the same <code>components<\/code> folder, create an <code>ImagePicker.vue<\/code> file containing the code snippet below:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-6\" 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\">template<\/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\">\"w-full mb-6\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h4<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"mb-4 font-semibold\"<\/span>&gt;<\/span>Add an image:<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h4<\/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\">\"flex\"<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>\n            <span class=\"hljs-attr\">v-for<\/span>=<span class=\"hljs-string\">\"image in imageList\"<\/span>\n            <span class=\"hljs-attr\">:key<\/span>=<span class=\"hljs-string\">\"image.id\"<\/span>\n            <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"border-2 cursor-pointer mr-2\"<\/span>\n            <span class=\"hljs-attr\">:class<\/span>=<span class=\"hljs-string\">\"&#91;\n              image.publicId === selectedImage ? 'border-red-400 border-4' : '',\n            ]\"<\/span>\n            @<span class=\"hljs-attr\">click<\/span>=<span class=\"hljs-string\">\"setActiveImage(image.publicId)\"<\/span>\n          &gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">v-if<\/span>=<span class=\"hljs-string\">\"image.id === 1\"<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"w-11 h-11 bg-white\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">cld-image<\/span> <span class=\"hljs-attr\">v-else<\/span> <span class=\"hljs-attr\">:public-id<\/span>=<span class=\"hljs-string\">\"image.publicId\"<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">cld-transformation<\/span> <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"45\"<\/span> <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">\"45\"<\/span> <span class=\"hljs-attr\">crop<\/span>=<span class=\"hljs-string\">\"thumb\"<\/span> \/&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">cld-image<\/span>&gt;<\/span>\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>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">template<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span>&gt;<\/span><span class=\"javascript\">\n    \n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> {\n      <span class=\"hljs-attr\">props<\/span>: {\n        <span class=\"hljs-attr\">imageList<\/span>: { <span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-built_in\">Array<\/span>, <span class=\"hljs-attr\">required<\/span>: <span class=\"hljs-literal\">true<\/span> },\n        <span class=\"hljs-attr\">setActiveImage<\/span>: { <span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-built_in\">Function<\/span>, <span class=\"hljs-attr\">required<\/span>: <span class=\"hljs-literal\">true<\/span> },\n        <span class=\"hljs-attr\">selectedImage<\/span>: { <span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-built_in\">String<\/span>, <span class=\"hljs-attr\">required<\/span>: <span class=\"hljs-literal\">true<\/span> },\n      },\n    }\n    <\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><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>The snippet above does the following:<\/p>\n<ul>\n<li>Configures the component to accept <code>imageList<\/code>, <code>setActiveImage<\/code>, and <code>selectedImage<\/code> props.<\/li>\n<li>Markup shows the list of the available images using Cloudinary component, sets the first item as active by default, and a click event to change the active image.<\/li>\n<\/ul>\n<p><strong>TextCustomPicker Component<\/strong>\nIn the same  <code>components<\/code> folder, create an <code>TextCustomPicker.vue<\/code> file containing the code snippet below:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-7\" 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\">template<\/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\">\"w-full mb-6\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h4<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"mb-4 font-semibold\"<\/span>&gt;<\/span>Add a text:<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h4<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">form<\/span> @<span class=\"hljs-attr\">submit.prevent<\/span>=<span class=\"hljs-string\">\"onSubmit\"<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">select<\/span>\n        <span class=\"hljs-attr\">v-model<\/span>=<span class=\"hljs-string\">\"activeFont\"<\/span>\n        @<span class=\"hljs-attr\">change<\/span>=<span class=\"hljs-string\">\"onChange($event)\"<\/span>\n        <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"font-picker\"<\/span>\n        <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"h-10 w-32 mb-3 border rounded\"<\/span>\n      &gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">option<\/span> <span class=\"hljs-attr\">v-for<\/span>=<span class=\"hljs-string\">\"(font, i) in fontList\"<\/span> <span class=\"hljs-attr\">:key<\/span>=<span class=\"hljs-string\">\"i\"<\/span> <span class=\"hljs-attr\">:value<\/span>=<span class=\"hljs-string\">\"font.value\"<\/span>&gt;<\/span>\n          {{ font.title }}\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">option<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">select<\/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\">\"flex\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span>\n          <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"text\"<\/span>\n          <span class=\"hljs-attr\">placeholder<\/span>=<span class=\"hljs-string\">\"enter text\"<\/span>\n          <span class=\"hljs-attr\">required<\/span>\n          <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"h-10 w-60 mr-2 pl-2 border rounded\"<\/span>\n          <span class=\"hljs-attr\">v-model<\/span>=<span class=\"hljs-string\">\"text\"<\/span>\n        \/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"px-4 bg-indigo-600 text-white rounded\"<\/span>&gt;<\/span>Add Text<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">form<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">template<\/span>&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span>&gt;<\/span><span class=\"javascript\">\n <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> {\n   <span class=\"hljs-attr\">props<\/span>: {\n     <span class=\"hljs-attr\">fontList<\/span>: { <span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-built_in\">Array<\/span>, <span class=\"hljs-attr\">required<\/span>: <span class=\"hljs-literal\">true<\/span> },\n     <span class=\"hljs-attr\">setActiveFont<\/span>: { <span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-built_in\">Function<\/span>, <span class=\"hljs-attr\">required<\/span>: <span class=\"hljs-literal\">true<\/span> },\n     <span class=\"hljs-attr\">setText<\/span>: { <span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-built_in\">Function<\/span>, <span class=\"hljs-attr\">required<\/span>: <span class=\"hljs-literal\">true<\/span> },\n     <span class=\"hljs-attr\">selectedFont<\/span>: { <span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-built_in\">String<\/span>, <span class=\"hljs-attr\">required<\/span>: <span class=\"hljs-literal\">true<\/span> },\n   },\n   data() {\n     <span class=\"hljs-keyword\">return<\/span> {\n       <span class=\"hljs-attr\">activeFont<\/span>: <span class=\"hljs-string\">''<\/span>,\n       <span class=\"hljs-attr\">text<\/span>: <span class=\"hljs-string\">''<\/span>,\n     }\n   },\n   <span class=\"hljs-attr\">methods<\/span>: {\n     onChange(event) {\n       <span class=\"hljs-keyword\">this<\/span>.setActiveFont(event.target.value)\n     },\n     onSubmit() {\n       <span class=\"hljs-keyword\">this<\/span>.setText(<span class=\"hljs-keyword\">this<\/span>.text)\n     },\n   },\n   mounted() {\n     <span class=\"hljs-keyword\">this<\/span>.activeFont = <span class=\"hljs-keyword\">this<\/span>.selectedFont\n   },\n }\n<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><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>The snippet above does the following:<\/p>\n<ul>\n<li>Configures the component to accept <code>fontList<\/code>, <code>setActiveFont<\/code>, <code>setText<\/code>, and <code>selectedFont<\/code> props.<\/li>\n<li>Create <code>data<\/code> properties to manage active font and custom text.<\/li>\n<li>Create <code>onChange<\/code> and <code>onSubmit<\/code> methods to change the active font and the custom text.<\/li>\n<li>Use the <code>mounted<\/code> lifecycle to set the active font when the component is rendered.<\/li>\n<li>Markup shows the list of the available fonts and a form to submit custom text changes.<\/li>\n<\/ul>\n<p><strong>ProductImage Component<\/strong>\nIn the same  <code>components<\/code> folder, create an <code>ProductImage.vue<\/code> file containing the code snippet below:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-8\" 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\">template<\/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\">\"lg:h-96\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">cld-image<\/span> <span class=\"hljs-attr\">public-id<\/span>=<span class=\"hljs-string\">\"Hanging_T-Shirt_v83je9\"<\/span> <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"500\"<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">cld-transformation<\/span> <span class=\"hljs-attr\">:effect<\/span>=<span class=\"hljs-string\">\"`replace_color:${selectedColor}`\"<\/span> \/&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">cld-transformation<\/span> <span class=\"hljs-attr\">:overlay<\/span>=<span class=\"hljs-string\">\"selectedImage\"<\/span> <span class=\"hljs-attr\">fetch-format<\/span>=<span class=\"hljs-string\">\"auto\"<\/span> <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">\"110\"<\/span> \/&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">cld-transformation<\/span>\n            <span class=\"hljs-attr\">:overlay<\/span>=<span class=\"hljs-string\">\"{\n              fontFamily: selectedFont,\n              fontSize: 33,\n              fontWeight: 'bold',\n              text: customText,\n            }\"<\/span>\n            <span class=\"hljs-attr\">gravity<\/span>=<span class=\"hljs-string\">\"center\"<\/span>\n            <span class=\"hljs-attr\">y<\/span>=<span class=\"hljs-string\">\"0.1\"<\/span>\n          \/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">cld-image<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">template<\/span>&gt;<\/span>\n    \n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span>&gt;<\/span><span class=\"javascript\">\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> {\n      <span class=\"hljs-attr\">props<\/span>: {\n        <span class=\"hljs-attr\">selectedColor<\/span>: { <span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-built_in\">String<\/span>, <span class=\"hljs-attr\">required<\/span>: <span class=\"hljs-literal\">true<\/span> },\n        <span class=\"hljs-attr\">selectedImage<\/span>: { <span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-built_in\">String<\/span>, <span class=\"hljs-attr\">required<\/span>: <span class=\"hljs-literal\">true<\/span> },\n        <span class=\"hljs-attr\">selectedFont<\/span>: { <span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-built_in\">String<\/span>, <span class=\"hljs-attr\">required<\/span>: <span class=\"hljs-literal\">true<\/span> },\n        <span class=\"hljs-attr\">customText<\/span>: { <span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-built_in\">String<\/span>, <span class=\"hljs-attr\">required<\/span>: <span class=\"hljs-literal\">true<\/span> },\n      },\n    }\n<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><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>The snippet above does the following:<\/p>\n<ul>\n<li>Configures the component to accept <code>selectedColor<\/code>, <code>selectedImage<\/code>,  <code>selectedFont<\/code>  and <code>customText<\/code> props.<\/li>\n<li>Configure <code>cld-image<\/code> and <code>cld-transformation<\/code>s to render the product image, overlay, and text. The <code>public-id<\/code> specified(<em><strong>Hanging_T-Shirt_v83je9<\/strong><\/em>) is for the product image we uploaded earlier.\nWe also leverage Cloudinary\u2019s support for multiple transformations to transform the image. We added the following transformations, <strong>cropping<\/strong>, <strong>replacing colour<\/strong>, adding overlays for <strong>images<\/strong>, <strong>text,<\/strong> <strong>text position<\/strong>**,** <strong>text properties<\/strong>, and <strong>flags<\/strong> to alter the positioning of the text.<\/li>\n<\/ul>\n<p><strong>Putting it all together<\/strong>\nWith that done, we can now start using the components to create the product customization. To do this, we modify <code>index.vue<\/code> file in the <code>pages<\/code> folder to the following:<\/p>\n<p><a href=\"https:\/\/gist.github.com\/Mr-Malomz\/f4be24396e8192334ed66a005649bc9e\">https:\/\/gist.github.com\/Mr-Malomz\/f4be24396e8192334ed66a005649bc9e<\/a><\/p>\n<p><a href=\"https:\/\/gist.github.com\/Mr-Malomz\/f4be24396e8192334ed66a005649bc9e\">https:\/\/gist.github.com\/Mr-Malomz\/f4be24396e8192334ed66a005649bc9e<\/a><\/p>\n<p>The snippet above does the following:<\/p>\n<ul>\n<li>Import the required JSON collections<\/li>\n<li>Create <code>data<\/code> properties to manage imported JSON collections, selected colour, selected image, selected font, custom text and key. The <strong>key<\/strong> property is required to trigger a re-render when any of the property changes.<\/li>\n<li>Create <code>setActiveColor<\/code>, <code>setActiveImage<\/code>, <code>setActiveFont<\/code>, and <code>setText<\/code> methods to change colours, images, fonts and text respectively. We also changed the <code>key<\/code> property in all the functions to trigger re-render accordingly.<\/li>\n<li>Markup to include the components and pass in the required props. In addition to the required props, we added the <code>key<\/code> props to the <code>ProductImage<\/code> component to track changes and re-render when needed.<\/li>\n<\/ul>\n<p>With that done, we can start a development server using the command below:<\/p>\n<pre><code>npm run dev\n<\/code><\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/media_jams\/s_1B7DF603BF129553B0BB8EA1D660CB8B1B30DC300EAD4CB5AA11C010096263A1_1642936982806_Screenshot+2022-01-23+at+12.22.45.png\" alt=\"working demo\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"2000\" height=\"958\"\/><\/p>\n<h1>Conclusion<\/h1>\n<p>This post discussed how to build a customizable product component using Cloudinary and Nuxt.js.<\/p>\n<p>You may find these resources helpful:<\/p>\n<ul>\n<li>\n<a href=\"https:\/\/cloudinary.nuxtjs.org\/\">Cloudinary Nuxt.js module<\/a>.<\/li>\n<li>\n<a href=\"https:\/\/tailwindcss.com\/\">TailwindCSS<\/a>.<\/li>\n<li>\n<a href=\"https:\/\/cloudinary.com\/documentation\/image_transformations#landingpage\">Cloudinary Image Transformation<\/a>.<\/li>\n<\/ul>\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":41,"featured_media":28519,"comment_status":"","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[384,134,370,372,371,315],"class_list":["post-28518","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-delivery","tag-guest-post","tag-image","tag-nuxtjs","tag-under-review","tag-vue"],"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>E-commerce product customization page in NuxtJS<\/title>\n<meta name=\"description\" content=\"This post will discuss how to build a customizable product component using Nuxt.js and Cloudinary.\" \/>\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\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"E-commerce product customization page in NuxtJS\" \/>\n<meta property=\"og:description\" content=\"This post will discuss how to build a customizable product component using Nuxt.js and Cloudinary.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-04-06T02:45:03+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924308\/Web_Assets\/blog\/27bf9d975d1f6a33ad7d1f33816fa3891a7f18f2-1012x506-1_28519e3228\/27bf9d975d1f6a33ad7d1f33816fa3891a7f18f2-1012x506-1_28519e3228.png?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"1012\" \/>\n\t<meta property=\"og:image:height\" content=\"506\" \/>\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\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"E-commerce product customization page in NuxtJS\",\"datePublished\":\"2022-04-06T02:45:03+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/\"},\"wordCount\":6,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924308\/Web_Assets\/blog\/27bf9d975d1f6a33ad7d1f33816fa3891a7f18f2-1012x506-1_28519e3228\/27bf9d975d1f6a33ad7d1f33816fa3891a7f18f2-1012x506-1_28519e3228.png?_i=AA\",\"keywords\":[\"Delivery\",\"Guest Post\",\"Image\",\"NuxtJS\",\"Under Review\",\"Vue\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2022\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/\",\"url\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/\",\"name\":\"E-commerce product customization page in NuxtJS\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924308\/Web_Assets\/blog\/27bf9d975d1f6a33ad7d1f33816fa3891a7f18f2-1012x506-1_28519e3228\/27bf9d975d1f6a33ad7d1f33816fa3891a7f18f2-1012x506-1_28519e3228.png?_i=AA\",\"datePublished\":\"2022-04-06T02:45:03+00:00\",\"description\":\"This post will discuss how to build a customizable product component using Nuxt.js and Cloudinary.\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924308\/Web_Assets\/blog\/27bf9d975d1f6a33ad7d1f33816fa3891a7f18f2-1012x506-1_28519e3228\/27bf9d975d1f6a33ad7d1f33816fa3891a7f18f2-1012x506-1_28519e3228.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924308\/Web_Assets\/blog\/27bf9d975d1f6a33ad7d1f33816fa3891a7f18f2-1012x506-1_28519e3228\/27bf9d975d1f6a33ad7d1f33816fa3891a7f18f2-1012x506-1_28519e3228.png?_i=AA\",\"width\":1012,\"height\":506},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"E-commerce product customization page in NuxtJS\"}]},{\"@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":"E-commerce product customization page in NuxtJS","description":"This post will discuss how to build a customizable product component using Nuxt.js and Cloudinary.","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\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/","og_locale":"en_US","og_type":"article","og_title":"E-commerce product customization page in NuxtJS","og_description":"This post will discuss how to build a customizable product component using Nuxt.js and Cloudinary.","og_url":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/","og_site_name":"Cloudinary Blog","article_published_time":"2022-04-06T02:45:03+00:00","og_image":[{"width":1012,"height":506,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924308\/Web_Assets\/blog\/27bf9d975d1f6a33ad7d1f33816fa3891a7f18f2-1012x506-1_28519e3228\/27bf9d975d1f6a33ad7d1f33816fa3891a7f18f2-1012x506-1_28519e3228.png?_i=AA","type":"image\/png"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/"},"author":{"name":"","@id":""},"headline":"E-commerce product customization page in NuxtJS","datePublished":"2022-04-06T02:45:03+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/"},"wordCount":6,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924308\/Web_Assets\/blog\/27bf9d975d1f6a33ad7d1f33816fa3891a7f18f2-1012x506-1_28519e3228\/27bf9d975d1f6a33ad7d1f33816fa3891a7f18f2-1012x506-1_28519e3228.png?_i=AA","keywords":["Delivery","Guest Post","Image","NuxtJS","Under Review","Vue"],"inLanguage":"en-US","copyrightYear":"2022","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/","url":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/","name":"E-commerce product customization page in NuxtJS","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924308\/Web_Assets\/blog\/27bf9d975d1f6a33ad7d1f33816fa3891a7f18f2-1012x506-1_28519e3228\/27bf9d975d1f6a33ad7d1f33816fa3891a7f18f2-1012x506-1_28519e3228.png?_i=AA","datePublished":"2022-04-06T02:45:03+00:00","description":"This post will discuss how to build a customizable product component using Nuxt.js and Cloudinary.","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924308\/Web_Assets\/blog\/27bf9d975d1f6a33ad7d1f33816fa3891a7f18f2-1012x506-1_28519e3228\/27bf9d975d1f6a33ad7d1f33816fa3891a7f18f2-1012x506-1_28519e3228.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924308\/Web_Assets\/blog\/27bf9d975d1f6a33ad7d1f33816fa3891a7f18f2-1012x506-1_28519e3228\/27bf9d975d1f6a33ad7d1f33816fa3891a7f18f2-1012x506-1_28519e3228.png?_i=AA","width":1012,"height":506},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-an-e-commerce-product-customization-page-in-nuxt-js\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"E-commerce product customization page in NuxtJS"}]},{"@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\/v1681924308\/Web_Assets\/blog\/27bf9d975d1f6a33ad7d1f33816fa3891a7f18f2-1012x506-1_28519e3228\/27bf9d975d1f6a33ad7d1f33816fa3891a7f18f2-1012x506-1_28519e3228.png?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28518","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=28518"}],"version-history":[{"count":0,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28518\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/28519"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=28518"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=28518"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=28518"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}