{
  "version": "https://jsonfeed.org/version/1",
  "items": [
    {
      "url": "https://hangindev.com/blog/avoid-flash-of-default-theme-an-implementation-of-dark-mode-in-react-app",
      "id": "avoid-flash-of-default-theme-an-implementation-of-dark-mode-in-react-app",
      "content_html": "<div><p>Have you ever visited a page and experienced a flash of light mode before transitioning into dark mode? Recently, I worked on a project that needs to support dark mode (since this is what the cool kids do 😜). After some research, I came across an implementation that can prevent the undesired flash of default theme and would like to write it down for you and my future self. </p><blockquote>This article is written for SSR/SSG React apps such as Next.js, GatsbyJS, but the same logic can be applied to single-page apps like CRA or other frameworks like Vuejs, Angular, etc.</blockquote><h2>Why the Flash?</h2><p>When implementing light/dark mode, <!-- -->one often has to reach for client-side-only features like <code>localStorage</code> or <code>prefers-color-scheme</code>. It means a default theme is required for the pre-rendered HTML and styles. When visitors open the page, the HTML elements are parsed and rendered with the default style before the update scheduled in a hook is fired, and thus the flash.</p><blockquote>Here is an example from <a href=\"https://usehooks.com/useDarkMode/\" target=\"_blank\" rel=\"noopener noreferrer\">usehooks.com/useDarkMode</a>.</blockquote><h2>A Better Implementation</h2><p>To prevent such a flash, we can extract the logic for managing themes in the React world and move it into a separate script placed above the HTML elements so that it will run before the HTML elements are parsed and rendered. </p><blockquote>I learned this implementation from the <a href=\"https://github.com/gaearon/overreacted.io/blob/master/src/html.js\" target=\"_blank\" rel=\"noopener noreferrer\">source code</a> of <a href=\"https://overreacted.io/\" target=\"_blank\" rel=\"noopener noreferrer\">Overreacted — A blog by Dan Abramov</a> which is created with GatsbyJS.</blockquote><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token doctype punctuation\" style=\"color:rgb(199, 146, 234);font-style:italic\">&lt;!</span><span class=\"token doctype doctype-tag\" style=\"color:rgb(199, 146, 234);font-style:italic\">DOCTYPE</span><span class=\"token doctype\" style=\"color:rgb(199, 146, 234);font-style:italic\"> </span><span class=\"token doctype name\" style=\"color:rgb(199, 146, 234);font-style:italic\">html</span><span class=\"token doctype punctuation\" style=\"color:rgb(199, 146, 234);font-style:italic\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">html</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">head</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">title</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\">Create Next App</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">title</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">&lt;!-- links to stylesheets --&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">head</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">body</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">script</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token script language-javascript\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token script language-javascript\">      </span><span class=\"token script language-javascript comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// 🌟 logic for managing themes goes here </span><span class=\"token script language-javascript\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token script language-javascript\">    </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">script</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">id</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">__next</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">&lt;!-- content --&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">script</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">src</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">/bundled.js</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token script\"></span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">script</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">body</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">html</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\" style=\"display:inline-block\">\n</span></div></pre><blockquote>To add the script, you will have to edit <code>_document.js</code> in Next.js projects or <code>html.js</code> in GatsbyJS projects. </blockquote><p>The script will do the following things:</p><ul><li>initializes a global <code>__onThemeChange</code> variable to be a no-op function which will be overwritten by our React component;</li><li>declares a global <code>__setPreferredTheme</code> function that when called, updates the body <code>className</code> and saves the chosen theme to <code>localStorage;</code></li><li>initializes theme to the saved theme in <code>localStorage</code>, fallback to system theme.</li></ul><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// wrapped as IIFE to use private variables and functions</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">setTheme</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token parameter\">newTheme</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token dom variable\" style=\"color:rgb(214, 222, 235)\">document</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">body</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">className</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> newTheme</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"> </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// \"dark\" or \"light\"</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token dom variable\" style=\"color:rgb(214, 222, 235)\">window</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">__theme</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> newTheme</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token dom variable\" style=\"color:rgb(214, 222, 235)\">window</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">__onThemeChange</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">newTheme</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// this will be overwritten in our React component</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token dom variable\" style=\"color:rgb(214, 222, 235)\">window</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method-variable function-variable method function property-access\" style=\"color:rgb(130, 170, 255)\">__onThemeChange</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// this will be triggered by our React component</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token dom variable\" style=\"color:rgb(214, 222, 235)\">window</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method-variable function-variable method function property-access\" style=\"color:rgb(130, 170, 255)\">__setPreferredTheme</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token parameter\">newTheme</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">setTheme</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">newTheme</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token keyword control-flow\" style=\"color:rgb(127, 219, 202)\">try</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token dom variable\" style=\"color:rgb(214, 222, 235)\">localStorage</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">setItem</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"theme\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token known-class-name class-name\" style=\"color:rgb(255, 203, 139)\">JSON</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">stringify</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token dom variable\" style=\"color:rgb(214, 222, 235)\">window</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">__theme</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"> </span><span class=\"token keyword control-flow\" style=\"color:rgb(127, 219, 202)\">catch</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">err</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// detect system theme and monitor for changes</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> darkQuery </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token dom variable\" style=\"color:rgb(214, 222, 235)\">window</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">matchMedia</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"(prefers-color-scheme: dark)\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  darkQuery</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">addListener</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token parameter\">event</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token dom variable\" style=\"color:rgb(214, 222, 235)\">window</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">__setPreferredTheme</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">event</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">matches</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">?</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"dark\"</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"light\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">let</span><span class=\"token plain\"> preferredTheme</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// try to get saved theme</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword control-flow\" style=\"color:rgb(127, 219, 202)\">try</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    preferredTheme </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token known-class-name class-name\" style=\"color:rgb(255, 203, 139)\">JSON</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">parse</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token dom variable\" style=\"color:rgb(214, 222, 235)\">localStorage</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">getItem</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"theme\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"> </span><span class=\"token keyword control-flow\" style=\"color:rgb(127, 219, 202)\">catch</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">err</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\">  </span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// initialize preferredTheme</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">setTheme</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">preferredTheme </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">||</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">darkQuery</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">matches</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">?</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"dark\"</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"light\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span></div></pre><blockquote>Please note the script is render-blocking so you should keep it short. Also, it will not be compiled by Babel so you should avoid using new JS features.</blockquote><p>In the global stylesheet, we can update the CSS variables based on the CSS className</p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token selector\" style=\"color:rgb(199, 146, 234);font-style:italic\">body</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token variable\" style=\"color:rgb(214, 222, 235)\">--background</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token plain\"> </span><span class=\"token hexcode color\">#faf4f8</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token variable\" style=\"color:rgb(214, 222, 235)\">--text-color</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token plain\"> </span><span class=\"token color function\" style=\"color:rgb(130, 170, 255)\">rgba</span><span class=\"token color punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token color number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token color punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token color\"> </span><span class=\"token color number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token color punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token color\"> </span><span class=\"token color number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token color punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token color\"> </span><span class=\"token color number\" style=\"color:rgb(247, 140, 108)\">0.87</span><span class=\"token color punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token variable\" style=\"color:rgb(214, 222, 235)\">--link</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token plain\"> </span><span class=\"token hexcode color\">#3182ce</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\" style=\"display:inline-block\">\n</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token selector\" style=\"color:rgb(199, 146, 234);font-style:italic\">body</span><span class=\"token selector class\" style=\"color:rgb(199, 146, 234);font-style:italic\">.dark</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token variable\" style=\"color:rgb(214, 222, 235)\">--background</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token plain\"> </span><span class=\"token hexcode color\">#1a202c</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token variable\" style=\"color:rgb(214, 222, 235)\">--text-color</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token plain\"> </span><span class=\"token hexcode color\">#f7fafc</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token variable\" style=\"color:rgb(214, 222, 235)\">--link</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token plain\"> </span><span class=\"token hexcode color\">#90cdf4</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span></div></pre><p>Now you can create your own <code>ThemeProvider</code> and <code>useTheme</code> hook to connect the global functions created.</p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">import</span><span class=\"token plain\"> React</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> useState</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> useEffect</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> useContext </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"react\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\" style=\"display:inline-block\">\n</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> ThemeContext </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> React</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">createContext</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"light\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\" style=\"display:inline-block\">\n</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">export</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">ThemeProvider</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token parameter punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token parameter\"> children </span><span class=\"token parameter punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">[</span><span class=\"token plain\">theme</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> setTheme</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">useState</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">global</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token plain\">window</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">?.</span><span class=\"token plain\">__theme </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">||</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"light\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> </span><span class=\"token function-variable function\" style=\"color:rgb(130, 170, 255)\">toggleTheme</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    global</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token plain\">window</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">__setPreferredTheme</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">theme </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">===</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"light\"</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">?</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"dark\"</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"light\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\" style=\"display:inline-block\">\n</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">useEffect</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    global</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token plain\">window</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token plain\">__onThemeChange </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> setTheme</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">[</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">]</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\" style=\"display:inline-block\">\n</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">return</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag class-name\" style=\"color:rgb(255, 203, 139)\">ThemeContext.Provider</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">value</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token tag script language-javascript\" style=\"color:rgb(127, 219, 202)\"> theme</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token tag script language-javascript\" style=\"color:rgb(127, 219, 202)\"> toggleTheme </span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\">children</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag class-name\" style=\"color:rgb(255, 203, 139)\">ThemeContext.Provider</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\" style=\"display:inline-block\">\n</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">export</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> </span><span class=\"token function-variable function\" style=\"color:rgb(130, 170, 255)\">useTheme</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">useContext</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">ThemeContext</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\" style=\"display:inline-block\">\n</span></div></pre><p>Here is a demo with Next.js:​ </p><div><iframe src=\"https://codesandbox.io/embed/themes-in-react-app-avoid-flash-of-default-theme-cxx8e?fontsize=14&amp;hidenavigation=1&amp;module=%2Fpages%2F_document.js&amp;theme=dark\" style=\"width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden; margin-bottom: 1rem\" title=\"themes-in-react-app-avoid-flash-of-default-theme\" allow=\"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking\" sandbox=\"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts\"></iframe></div><p>For implementation in GatsbyJS, you may check out the <a href=\"https://github.com/gaearon/overreacted.io/blob/master/src/html.js\" target=\"_blank\" rel=\"noopener noreferrer\">source code</a> of Dan Abramov's blog — <a href=\"https://overreacted.io/\" target=\"_blank\" rel=\"noopener noreferrer\">Overreacted.io</a>. I learned this approach from it.<!-- --> </p><h2>Afterthoughts</h2><p>When developing React apps, we tend to do everything with React and put every logic inside React components. The experience of implementing themes reminds me it is okay to write code outside of the React world and later bind it to React. After all, React is just <!-- -->a library for building user interfaces. In this case, understanding <!-- -->how browser rendering works is <!-- -->essential to create a smooth user experience. </p><p>Thank you for reading. <em>Ciao!</em></p></div>",
      "title": "Avoid Flash of Default Theme: An Implementation of Dark Mode in React App",
      "summary": "Have you ever visited a page and experienced a flash of light mode before transitioning into dark mode? In this article, I shared my experience implementing dark mode without the undesired flash of default theme.",
      "image": "https://cdn.sanity.io/images/mus2e14o/production/28452a4c6c32f425f6eb492443fd9ddffd4645e9-1200x630.jpg?w=1200&h=630",
      "banner_image": "https://cdn.sanity.io/images/mus2e14o/production/28452a4c6c32f425f6eb492443fd9ddffd4645e9-1200x630.jpg?w=1200&h=630",
      "date_published": "2020-09-13T03:28:19Z",
      "author": {
        "name": "Jason Leung",
        "url": "https://twitter.com/hangindev",
        "avatar": "https://cdn.sanity.io/images/mus2e14o/production/6e3427d0324c88bbe86a0e0544f416779c4fc9e6-256x256.png?w=128"
      }
    },
    {
      "url": "https://hangindev.com/blog/recreating-instagram-filter-functionality-with-css-and-canvas-apis",
      "id": "recreating-instagram-filter-functionality-with-css-and-canvas-apis",
      "content_html": "<div><p>Recreating UI components, especially those in native apps, has always led me to interesting unknown web APIs. It also helps me see things from the app developers' perspective and understand why a particular task is done in a particular way. Going forward, I will jot down the making-of of each clone and share the lessons I've learned. I hope you will also learn a thing or two and starting cloning your favorite components.</p><p>Today, I want to share my recent clone of the Instagram Filter page which turned out to be much simpler than I expected <em>(if I ignore a browser</em>).</p><blockquote><strong>Goal</strong>: Users can select a photo from their device, apply filters, see preview, and export(download) the result.</blockquote><div class=\"relative w-full mb-4\" style=\"padding-top:56.25%\"><div style=\"width:100%;height:100%\" class=\"absolute top-0 left-0\"></div></div><p><strong><a href=\"https://n35w3.csb.app/\" target=\"_blank\" rel=\"noopener noreferrer\">Live Demo</a></strong></p><p><strong><a href=\"https://codesandbox.io/s/nifty-lichterman-n35w3?fontsize=14&amp;hidenavigation=1&amp;theme=dark\" target=\"_blank\" rel=\"noopener noreferrer\">CodeSandbox</a></strong></p><h2>The Process<strong></strong></h2><p>Each Instagram filter is made of a set of basic filter effects, e.g. brightness, contrast, saturate, etc, and some overlays. With the help of CSS <code>filter</code> and <code>mix-blend-mode</code>, stacking filters and overlays to recreate an Instagram filter is pretty much an eyeballing task. Thanks to <a href=\"https://una.im/CSSgram/\" target=\"_blank\" rel=\"noopener noreferrer\">this brilliant work</a> by <a href=\"https://twitter.com/una\" target=\"_blank\" rel=\"noopener noreferrer\">Una</a> which did exactly that, <a href=\"https://una.im/CSSgram/\" target=\"_blank\" rel=\"noopener noreferrer\"></a>75% of my goal is completed. From there, I only have to figure out a way to export the result out since the CSS is changing the appearance but not the actual image. Luckily, I found there are two Canvas APIs that do very similar things and they are canvas <code>filter</code> and <code>globalCompositeOperation.</code> With them, I can perform the same operation to the image drawn on canvas and use the method <code>toDataURL</code> to export it out. 🍬</p><blockquote>Unfortunately, the canvas filter API is experimental and is only supported in Chrome, Firefox, Edge, but not in Safari. So the clone is not fully functioning on the iPhone. <strong><em>augh, safari!</em></strong></blockquote><h2>Some Details</h2><p>You can see the full implementation in <a href=\"https://codesandbox.io/s/nifty-lichterman-n35w3?fontsize=14&amp;hidenavigation=1&amp;theme=dark\" target=\"_blank\" rel=\"noopener noreferrer\">the CodeSandbox</a>. Note that the exporting function does not work in CodeSandbox's <code>iframe</code> browser, open the app in a new window instead. Here are some implementation details:</p><p>I used an array to store the filter configurations:</p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// effects.js</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> effects </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">[</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> </span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    name</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"noraml\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    filter</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"none\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    overlays</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">[</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">]</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    name</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"clarendon\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    filter</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"contrast(1.2) saturate(1.35)\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    overlays</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">[</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        backgroundColor</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"rgba(127, 187, 227, 0.2)\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        mixBlendMode</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"overlay\"</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">]</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">]</span></div></pre><p>When the \"clarendon\" filter is turned into HTML and CSS:</p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">&lt;!--image with \"Clarendon\" filter applied --&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">figure</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag style-attr attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">style</span><span class=\"token tag style-attr attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag style-attr attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag style-attr attr-value style language-css property\" style=\"color:rgb(128, 203, 196)\">filter</span><span class=\"token tag style-attr attr-value style language-css punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token tag style-attr attr-value style language-css\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag style-attr attr-value style language-css function\" style=\"color:rgb(130, 170, 255)\">contrast</span><span class=\"token tag style-attr attr-value style language-css punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token tag style-attr attr-value style language-css number\" style=\"color:rgb(247, 140, 108)\">1.2</span><span class=\"token tag style-attr attr-value style language-css punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token tag style-attr attr-value style language-css\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag style-attr attr-value style language-css function\" style=\"color:rgb(130, 170, 255)\">saturate</span><span class=\"token tag style-attr attr-value style language-css punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token tag style-attr attr-value style language-css number\" style=\"color:rgb(247, 140, 108)\">1.35</span><span class=\"token tag style-attr attr-value style language-css punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token tag style-attr attr-value style language-css punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token tag style-attr attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">img</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">src</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">/plitvice-lakes.jpg</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag style-attr attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">style</span><span class=\"token tag style-attr attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag style-attr attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag style-attr attr-value style language-css property\" style=\"color:rgb(128, 203, 196)\">background-color</span><span class=\"token tag style-attr attr-value style language-css punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token tag style-attr attr-value style language-css\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag style-attr attr-value style language-css color function\" style=\"color:rgb(130, 170, 255)\">rgba</span><span class=\"token tag style-attr attr-value style language-css color punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token tag style-attr attr-value style language-css color number\" style=\"color:rgb(247, 140, 108)\">127</span><span class=\"token tag style-attr attr-value style language-css color punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token tag style-attr attr-value style language-css color\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag style-attr attr-value style language-css color number\" style=\"color:rgb(247, 140, 108)\">187</span><span class=\"token tag style-attr attr-value style language-css color punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token tag style-attr attr-value style language-css color\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag style-attr attr-value style language-css color number\" style=\"color:rgb(247, 140, 108)\">227</span><span class=\"token tag style-attr attr-value style language-css color punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token tag style-attr attr-value style language-css color\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag style-attr attr-value style language-css color number\" style=\"color:rgb(247, 140, 108)\">0.2</span><span class=\"token tag style-attr attr-value style language-css color punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token tag style-attr attr-value style language-css punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token tag style-attr attr-value style language-css\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag style-attr attr-value style language-css property\" style=\"color:rgb(128, 203, 196)\">mix-blend-mode</span><span class=\"token tag style-attr attr-value style language-css punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token tag style-attr attr-value style language-css\" style=\"color:rgb(127, 219, 202)\"> overlay</span><span class=\"token tag style-attr attr-value style language-css punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token tag style-attr attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">figure</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span></div></pre><p>This is how a Instagram filter(i called it <code>effect</code> in the code) is applied on canvas:</p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">applyEffect</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token parameter\">name</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// find effect by name</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> effect </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> effects</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">find</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token parameter\">eff</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:rgb(127, 219, 202)\">=&gt;</span><span class=\"token plain\"> eff</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">name</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">===</span><span class=\"token plain\"> name</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> width</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> height </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> previewCanvas</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// clear canvas</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  ctx</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">clearRect</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> width</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> height</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// apply filter</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  ctx</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">filter</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> effect</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">filter</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// draw the image</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  ctx</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">globalCompositeOperation</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"source-over\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  ctx</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">drawImage</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">previewImg</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> width</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> height</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// loop through overlays and fill with corresponding color and blend mode</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  effect</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">overlays</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">forEach</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token parameter\">overlay</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:rgb(127, 219, 202)\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    ctx</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">globalCompositeOperation</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> overlay</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">mixBlendMode</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\">ctx</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">fillStyle</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> overlay</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">backgroundColor</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    ctx</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">fillRect</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> width</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> height</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span></div></pre><h2>Lessons Learned</h2><ul><li>Both CSS <code>filter</code> and <code>mix-blend-mode</code> are handy if you want to alter the look of your page without reaching for graphics editors. They can be applied to not only image but every element.</li><li>Canvas declarative <code>filter</code> API lower the entry barriers to image processing.</li><li>These APIs all make use of the GPU so they are performant.</li><li>The CSS properties have wide browser support but not the canvas <code>filter</code> API.</li><li>For production, use WebGL or a thrid-party library instead.</li><li><del>Safari is the new IE</del>.</li></ul><h2>Afterthoughts</h2><p>Since I had played with WebGL before, I am well aware these effects can be achieved using WebGL. (Take a look at <a href=\"https://gl-react-cookbook.surge.sh/\" target=\"_blank\" rel=\"noopener noreferrer\">gl-react</a> if you are a React developer) But this time, I am experimenting with an even simpler solution. And thanks to the declarative APIs (<em>and also CSSgram!</em>), recreating those Instagram effects and the export function is not complicated at all. I am interested in how you are using these CSS properties so please let me know! 😉</p><p>Thank you for reading! <em>Until next time! 👋</em></p></div>",
      "title": "Recreating Instagram Filter Functionality with CSS and Canvas APIs",
      "summary": "Recreating UI components has always led me to interesting unknown web APIs. In this article, I want to share my recent clone of the Instagram Filter page which turned out to be much simpler than I expected.",
      "image": "https://cdn.sanity.io/images/mus2e14o/production/e800e5149b226f80500b889170183f3450ec0e63-1200x630.jpg?w=1200&h=630",
      "banner_image": "https://cdn.sanity.io/images/mus2e14o/production/e800e5149b226f80500b889170183f3450ec0e63-1200x630.jpg?w=1200&h=630",
      "date_published": "2020-06-29T07:01:20Z",
      "author": {
        "name": "Jason Leung",
        "url": "https://twitter.com/hangindev",
        "avatar": "https://cdn.sanity.io/images/mus2e14o/production/6e3427d0324c88bbe86a0e0544f416779c4fc9e6-256x256.png?w=128"
      }
    },
    {
      "url": "https://hangindev.com/blog/rgb-splitting-effect-with-html5-canvas-and-javascript",
      "id": "rgb-splitting-effect-with-html5-canvas-and-javascript",
      "content_html": "<div><p>Recently, I followed <a href=\"https://twitter.com/honeypotio\" target=\"_blank\" rel=\"noopener noreferrer\">Honeypot</a> on Twitter. In case you didn't know, Honeypot is a developer-focused job platform that also produces awesome documentaries exploring tech culture and influential technologies. On their page, they like to use this RGB splitting technique in their cover images to create a glitch effect. <em>Neat.</em> So I figured I'd write a post explaining how it can be done with HTML5 canvas and JavaScript to those who are new to image processing on the web.</p><figure class=\"text-center\"><div class=\"relative overflow-hidden md:rounded shadow-xl\"><div style=\"padding-bottom:47.625%\"></div><img loading=\"lazy\" class=\"absolute w-full h-full inset-0 object-cover object-center opacity-0 transition duration-700 ease-in-out transition-opacity\" src=\"https://cdn.sanity.io/images/mus2e14o/production/023984430eb5cc99c03490148e8e1e50f0f10ba5-800x381.jpg\" alt=\"Screenshot of Honeypot page\"></div><figcaption class=\"text-xs text-gray-800 mt-1\">Honeypot likes to use this RGB splitting effect on their page.</figcaption></figure><h2>Walk-through 🚶‍♀️🚶‍♂️</h2><p>In the end result, there are an <code>img</code> element and <code>canvas</code> element placed side by side to show the before-after comparison. Below there are three sliders which are <code>input</code> elements with type \"range\". When you adjust the slider, you will see the splitting effect on the <code>canvas</code>. </p><p><a href=\"https://hangindev.com/demo/rgb-splitting.html\" target=\"_blank\" rel=\"noopener noreferrer\">Live demo</a></p><p>I created <a href=\"https://codesandbox.io/s/focused-bogdan-y68xc?fontsize=14&amp;hidenavigation=1&amp;theme=dark\" target=\"_blank\" rel=\"noopener noreferrer\">this CodeSandbox</a> for you to follow along. Let's walk through the files. First, I scaffolded the structure inside <code>body</code> of <code>index.html</code> so that we can focus on writing JavaScript. I also added a stylesheet in the <code>head</code> which I will not go into here but feel free to have a look. </p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">body</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">&lt;!-- Before / After --&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">class</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">container</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">p</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\">Original Image:</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">p</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">img</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">id</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">Source</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">src</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">/demo.jpg</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">crossorigin</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">anonymous</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">/&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">p</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\">Canvas:</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">p</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">canvas</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">id</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">Canvas</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">canvas</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">&lt;!-- Control Sliders --&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">class</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">control</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">class</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">red</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">label</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\">R:</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">label</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">input</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">id</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">rOffset</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">type</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">range</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">min</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">-100</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">max</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">100</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">step</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">5</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">/&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">class</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">green</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">label</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\">G:</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">label</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">input</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">id</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">gOffset</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">type</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">range</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">min</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">-100</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">max</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">100</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">step</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">5</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">/&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">class</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">blue</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">label</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\">B:</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">label</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">input</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">id</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">bOffset</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">type</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">range</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">min</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">-100</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">max</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">100</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">step</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">5</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">/&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">&lt;!-- Reference the external script --&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">script</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">src</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">app.js</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token script\"></span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">script</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">body</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span></div></pre><blockquote>The <code>crossorigin=\"anonymous\"</code> attribute on the <code>img</code> tag tells the browser to fetch the image with CORS(Cross-Origin Resource Sharing) header. I will write more about CORS in the future. For now, just keep in mind if you fail to do some operations on a <code>canvas</code>, it may be related to CORS.</blockquote><p>Then there are two js files. <code>app.js</code> contains the minimal code to get you started. If at every time you want to look at the finished code, you can check <code>app-finish.js.</code></p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// Find all elements that will be used and assign them to variables</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> image </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token dom variable\" style=\"color:rgb(214, 222, 235)\">document</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">getElementById</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"Source\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> canvas </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token dom variable\" style=\"color:rgb(214, 222, 235)\">document</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">getElementById</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"Canvas\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> rOffsetInput </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token dom variable\" style=\"color:rgb(214, 222, 235)\">document</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">getElementById</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"rOffset\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> gOffsetInput </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token dom variable\" style=\"color:rgb(214, 222, 235)\">document</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">getElementById</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"gOffset\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> bOffsetInput </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token dom variable\" style=\"color:rgb(214, 222, 235)\">document</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">getElementById</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"bOffset\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// If the image is completely loaded before this script executes, call init().</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token keyword control-flow\" style=\"color:rgb(127, 219, 202)\">if</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">image</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">complete</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">init</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// In case it is not loaded yet, we listen to its \"load\" event and call init() when it fires.</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">image</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">addEventListener</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"load\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> init</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\" style=\"display:inline-block\">\n</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">init</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// Where the Magic Happens</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span></div></pre><h2>Display the Image on Canvas </h2><p>For any image processing tasks you'd like to perform, you will most likely need to use the <code>canvas</code> element. <code>canvas</code> is a powerful playground for you to play with image data, apply filters and overlays effects. And you are not limited to static images but you can even manipulate video data with <code>canvas</code>. Here let's first try to draw the image from the <code>img</code> element to the <code>canvas</code>.</p><p>To draw anything on the canvas, you will need to get a drawing context using <strong><code>getContext</code></strong> method. \"2d\" is passed as argument to get a two-dimensional rendering context. Then, we will set the canvas drawing dimensions (as opposed to the display dimensions set by CSS) to the intrinsic width and height of the image. Finally, we will use the <strong><code>drawImage</code></strong> method to draw the image onto the canvas. (Save the file using ctrl+s/cmd+s after changes to see the update.)</p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">init</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> ctx </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> canvas</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">getContext</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"2d\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> width </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> image</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">naturalWidth</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> height </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> image</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">naturalHeight</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  canvas</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">width</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> width</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  canvas</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">height</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> height</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  ctx</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">drawImage</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">image</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> width</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> height</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span></div></pre><blockquote><strong>Syntax:</strong> drawImage(<em>image, dx, dy, dWidth, dHeight</em>) where <em>image </em>is the image elemnet to show, <em>dx, dy</em> are the x and y coordinate in the canvas at which to place the top-left corner of the image, and <em>dWidth,</em> <em>dHeight </em>are the width and height to draw the image in the canvas.</blockquote><h2>Peek into the ImageData</h2><p>Now, let's use <code>getImageData</code> to get the image data out and see what is in it using <code>console.log</code>. Do not use the console CodeSandbox provides since the I<code>mageData</code> object is a fairly large object. Instead, open the browser in a new window and use the native console of the browser.</p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">init</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> ctx </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> canvas</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">getContext</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"2d\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> width </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> image</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">naturalWidth</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> height </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> image</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">naturalHeight</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  canvas</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">width</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> width</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  canvas</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">height</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> height</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  ctx</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">drawImage</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">image</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> width</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> height</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// 👇</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> imageData </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> ctx</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">getImageData</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> width</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> height</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token console class-name\" style=\"color:rgb(255, 203, 139)\">console</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">log</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">imageData</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span></div></pre><blockquote><strong>Syntax</strong>: ctx.getImageData(<em>sx, sy, sw, sh</em>) where <em>sx, sy</em> are the x and y coordinate of the top-left corner of the rectangle from which the data will be extracted, and <em>sw, sh</em> are the width and height of the rectangle from which the data will be extracted.</blockquote><p>The i<code>mageData</code> object has three properties: <code>width</code> and <code>height</code> are the actual dimensions of the image data we extracted, which in this case is also the dimensions of our image and canvas. The <code>data</code> property is an <code>Uint8ClampedArray</code> which is an array-like object used to store values between 0-255(inclusive). Values smaller than 0 or greater than 255 will be clamped to 0 and 255. </p><p>So what is this array representing? If you have used <code>rgb</code> color in CSS, you may have a sense that it is something related and you are right. This <code>Uint8ClampedArray</code> is a one-dimensional array representing the color in the RGBA(red, green, blue, alpha) order of every pixel in the image. In other words, every four values in this array represent a pixel in the image.</p><blockquote>ImageData {data: Uint8ClampedArray[14, 34, 58, 255, 38, 60, 81, 255, 46, 75, 93, 255…], width: 640, height: 427}</blockquote><h2>Time to Tear Them Apart</h2><p>Now that we've learned about <code>ImageData</code>. It's time for the fun part. (<em>finally!</em>) The idea behind the RGB splitting is to shift the whole channel of color(red, green or blue) in different directions. To implement it, we will create a helper function called <code>rgbSplit</code>. (create it above or below the <code>init</code> function)</p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">rgbSplit</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token parameter\">imageData</span><span class=\"token parameter punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token parameter\"> options</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// destructure the offset values from options, default to 0</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> rOffset </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> gOffset </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> bOffset </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> options</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"> </span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// clone the pixel array from original imageData</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> originalArray </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> imageData</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">data</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> newArray </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">new</span><span class=\"token plain\"> </span><span class=\"token class-name\" style=\"color:rgb(255, 203, 139)\">Uint8ClampedArray</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">originalArray</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// loop through every pixel and assign values to the offseted position</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword control-flow\" style=\"color:rgb(127, 219, 202)\">for</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">let</span><span class=\"token plain\"> i </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"> i </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">&lt;</span><span class=\"token plain\"> originalArray</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">length</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"> i </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">+=</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">4</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    newArray</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">[</span><span class=\"token plain\">i </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">+</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">+</span><span class=\"token plain\"> rOffset </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">*</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">4</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> originalArray</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">[</span><span class=\"token plain\">i </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">+</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">]</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"> </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// 🔴</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    newArray</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">[</span><span class=\"token plain\">i </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">+</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">1</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">+</span><span class=\"token plain\"> gOffset </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">*</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">4</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> originalArray</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">[</span><span class=\"token plain\">i </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">+</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">1</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">]</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"> </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// 🟢</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    newArray</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">[</span><span class=\"token plain\">i </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">+</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">2</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">+</span><span class=\"token plain\"> bOffset </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">*</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">4</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> originalArray</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">[</span><span class=\"token plain\">i </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">+</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">2</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">]</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"> </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// 🔵</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// return a new ImageData object</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword control-flow\" style=\"color:rgb(127, 219, 202)\">return</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">new</span><span class=\"token plain\"> </span><span class=\"token class-name\" style=\"color:rgb(255, 203, 139)\">ImageData</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">newPixels</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> imageData</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">width</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> imageData</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">height</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span></div></pre><p><code>rgbSplit</code> takes in <code>ImageData</code> and an <code>options</code> object as arguments. The <code>options</code> object should have three properties: <code>rOffset</code>, <code>gOffset</code>, <code>bOffset</code> which represent the pixel offset of each color channel.</p><p>Next, instead of mutating the data values in <code>ImageData</code>, let's make a copy of it by calling the <code>Uint8ClampedArray</code> constructor and passing it the original color array. Then, we will loop through every pixel and manipulate the color in each of them. Remember four values in that array represent one pixel? That's why we are setting the increment expression to be <code>i += 4</code>.</p><p>In each iteration, we take each color intensity from the original array and place it to a new position based on the offset value provided. Again, we are multiplying the offset value by 4 since four values represent one pixel.</p><p>🔴🟢🔵⚪ 🔴🟢🔵⚪ 🔴🟢🔵⚪ 🔴🟢🔵⚪</p><p>To use the <code>rgbSplit</code> funciton, we go back into the <code>init</code> function. We call the <code>rgbSplit</code> funciton with the <code>imageData</code> we got from the canvas context and also some random offset values. We will then paint the new image data onto the canvas using the <strong><code>putImageData</code></strong> method. </p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">init</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> ctx </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> canvas</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">getContext</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"2d\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> width </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> image</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">naturalWidth</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> height </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> image</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">naturalHeight</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  canvas</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">width</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> width</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  canvas</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">height</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> height</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  ctx</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">drawImage</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">image</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> width</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> height</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> imageData </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> ctx</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">getImageData</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> width</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> height</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// 👇</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> updatedImageData </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">rgbSplit</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">imageData</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    rOffset</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">20</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    gOffset</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">-</span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">10</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    bOffset</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">10</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  ctx</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">putImageData</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">updatedImageData</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span></div></pre><blockquote><strong>Syntax</strong>: ctx.putImageData(<em>imageData</em>, <em>dx</em>, <em>dy</em>) where <em>imageData</em> is the <code>ImageData</code> object containing the array of pixel values and <code>dx, dy</code> are the x and y coordinate at which to place the image data in the destination canvas.</blockquote><figure class=\"text-center\"><div class=\"relative overflow-hidden md:rounded shadow-xl\"><div style=\"padding-bottom:37.8%\"></div><img loading=\"lazy\" class=\"absolute w-full h-full inset-0 object-cover object-center opacity-0 transition duration-700 ease-in-out transition-opacity\" src=\"https://cdn.sanity.io/images/mus2e14o/production/32467ad895e856c5d16aab88625cab6b7afdc394-1000x378.png\" alt=\"Images with and without RGB splitting effect applied\"></div></figure><h4>And <em>voila.</em></h4><div><iframe src=\"https://giphy.com/embed/WrBSHRLE9gEgM\" width=\"330\" height=\"480\" frameborder=\"0\" class=\"giphy-embed\" style=\"margin: 0 auto;\" allowfullscreen=\"\"></iframe><p style=\"text-align: center;\"><a href=\"https://giphy.com/gifs/chris-evans-WrBSHRLE9gEgM\">via GIPHY</a></p></div><h2>Bonus: Implement the Sliders</h2><p>Lastly, with the help of the <code>rgbSplit</code> function, the implementation of the slider control will be straightforward. We just have to listen to the slider \"change\" event and call the <code>rgbSplit</code> function with the values of the sliders.</p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">init</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> ctx </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> canvas</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">getContext</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"2d\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> width </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> image</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">naturalWidth</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> height </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> image</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">naturalHeight</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  canvas</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">width</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> width</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  canvas</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">height</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> height</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  ctx</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">drawImage</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">image</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> width</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> height</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> imageData </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> ctx</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">getImageData</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> width</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> height</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\" style=\"display:inline-block\">\n</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// const updatedImageData = rgbSplit(imageData, {</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">//   rOffset: 30,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">//   gOffset: -10,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">//   bOffset: 10</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// });</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// ctx.putImageData(updatedImageData, 0, 0);</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\" style=\"display:inline-block\">\n</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  rOffsetInput</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">addEventListener</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"change\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> updateCanvas</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  gOffsetInput</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">addEventListener</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"change\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> updateCanvas</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  bOffsetInput</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">addEventListener</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"change\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> updateCanvas</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// Put this function inside init since we have to access imageData</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">updateCanvas</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> updatedImageData </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">rgbSplit</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">imageData</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// turn string value into integer</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      rOffset</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token known-class-name class-name\" style=\"color:rgb(255, 203, 139)\">Number</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">rOffsetInput</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">value</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      gOffset</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token known-class-name class-name\" style=\"color:rgb(255, 203, 139)\">Number</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">gOffsetInput</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">value</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      bOffset</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token known-class-name class-name\" style=\"color:rgb(255, 203, 139)\">Number</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">bOffsetInput</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">value</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    ctx</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">putImageData</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">updatedImageData</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span></div></pre><h2>Wrap up</h2><p>Are you still here? What's meant to be a simple article has turned into one of my longest posts. But I hope you have learned something and get to play with the <code>canvas</code> element. Please let me know your feedback. Do you think if the post is too lengthy? Or did I not explain some concepts well enough? Anyway, thanks a lot for reading. <em>Until next time! 👋</em></p><h5><a href=\"https://twitter.com/hangindev/status/1276861865797156869\" target=\"_blank\" rel=\"noopener noreferrer\">Discuss on Twitter</a>  • <a href=\"https://dev.to/hangindev/rgb-splitting-effect-with-html5-canvas-and-javascript-1c4f\" target=\"_blank\" rel=\"noopener noreferrer\">Discuss on DEV</a></h5><blockquote>I am planning to write about an <strong>Instagram Effect Clone</strong> with actual functionality and I hope to make it beginner-friendly using just plain HTML, CSS, and JavaScript so that more people can try. It will probably be split into 2 parts? If you would like to get the latest updates, please <a href=\"https://twitter.com/hangindev\" target=\"_blank\" rel=\"noopener noreferrer\">follow me on twitter</a>. 😉</blockquote><div><div><video src=\"https://hangindev.com/demo/instagram-clone.mp4\" controls=\"\" muted=\"\" style=\"margin: 0 auto; width: 400px; max-width: 100%; height: auto;\"></video></div></div><p></p></div>",
      "title": "RGB Splitting Effect with HTML5 Canvas and JavaScript",
      "summary": "In this article, I explain how an RGB splitting effect can be done with HTML5 canvas and JavaScript to those who are new to image processing on the web.",
      "image": "https://cdn.sanity.io/images/mus2e14o/production/42792a2bed4360cfa7fefdb1e08014522b3fb489-1200x630.jpg?w=1200&h=630",
      "banner_image": "https://cdn.sanity.io/images/mus2e14o/production/42792a2bed4360cfa7fefdb1e08014522b3fb489-1200x630.jpg?w=1200&h=630",
      "date_published": "2020-06-27T00:10:52Z",
      "author": {
        "name": "Jason Leung",
        "url": "https://twitter.com/hangindev",
        "avatar": "https://cdn.sanity.io/images/mus2e14o/production/6e3427d0324c88bbe86a0e0544f416779c4fc9e6-256x256.png?w=128"
      }
    },
    {
      "url": "https://hangindev.com/blog/generate-sitemap-and-rss-for-vercel-next-js-app-with-dynamic-routes",
      "id": "generate-sitemap-and-rss-for-vercel-next-js-app-with-dynamic-routes",
      "content_html": "<div><p>Recently, I had an interesting problem to solve — generate a <code>sitemap.xml</code> and an RSS feed endpoint for this blog which is built with <strong>Next.js</strong> and uses <strong>Sanity</strong> as the content backend. The post pages are dynamic routes that fetch content from Sanity for pre-rendering. The tricky part is to make sure the sitemap and RSS are in sync with the pages dynamically generated. In this post, I will share how I solve it by generating the files using a <code>postbuild</code> script and config ​<strong>Vercel</strong> Routes to handle the request.</p><blockquote>The solution I took is specific to my setup in which I deploy my serverless Next.js app to the Vercel platform. But the concept should be transferable to your use cases.</blockquote><h2>The \"Problem\"</h2><p>There are no APIs in Next.js that generate a sitemap or RSS based on the complied build results. Solutions suggested usually only work without dynamic routes.</p><h2>Requirements</h2><ul><li>The generation of the files(<code>sitemap.xml</code> and <code>feed.json</code>) should be automated in the build process.</li><li>The generation should base on the pre-rendered HTML files since the content stored in my CMS needed to be serialized into React components(same if you are using MDX) and I don't want to duplicate the work that Next.js has done for me. </li><li>The files should be built ahead of request. That means I am not using Next.js API routes to perform the task even though it is possible and valid.</li></ul><h2>Solution</h2><h4>Overview</h4><p>I created a <code>postbuild</code> script that searches for any pre-rendered HTML files inside the output <code>pages</code> folder and parses the files using <code>cheerio</code> to extract data. The data will then be used to create <code>sitemap.xml</code> and <code>feed.json</code> which will be written to the output <code>static</code> folder. Lastly, I configured the <code>vercel.json</code> file to route the requests to <code>/sitemap.xml</code> and <code>/feed.json</code> to the corresponding files in the static folder. Below are some implementation details:</p><h4>Add a <code>postbuild</code> script in <code>package.json</code>:</h4><p>It will be run by automatically <code>npm</code> or <code>yarn</code> after <code>build</code> script is executed. (All scripts support <code>pre</code> and <code>post</code> hooks. Learn more about that <a href=\"https://docs.npmjs.com/misc/scripts\" target=\"_blank\" rel=\"noopener noreferrer\">here</a>)</p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">\"scripts\"</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">\"dev\"</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"next dev\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">\"build\"</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"next build\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">\"start\"</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"next start\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">\"postbuild\"</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"node ./scripts/postbuild\"</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">\"...\"</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"...\"</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span></div></pre><h4>Create <code>/scripts/postbuild.js</code></h4><p>I will break it down piece by piece. First the main function:</p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">main</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> pagesDir </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'./.next/serverless/pages'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> pageFiles </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">getPageFiles</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">pagesDir</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">buildRss</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">pageFiles</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> pagesDir</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">buildSiteMap</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">pageFiles</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span></div></pre><p>The output pages directory in Vercel environment is located in <code>./.next/serverless/pages</code>. If you want to test in local environment, the output pages directory is located in <code>./.next/server/static/${buildId}/pages</code> and you can find the <code>buildId</code> in <code>./.next/BUILD_ID</code>.</p><p>The <code>getPageFiles</code> simply collect all the HTML files (excluding 404.html) in the output <code>pages</code> directory.</p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> fs </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">require</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'fs'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> path </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">require</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'path'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\" style=\"display:inline-block\">\n</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">getPageFiles</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token parameter\">directory</span><span class=\"token parameter punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token parameter\"> files </span><span class=\"token parameter operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token parameter\"> </span><span class=\"token parameter punctuation\" style=\"color:rgb(199, 146, 234)\">[</span><span class=\"token parameter punctuation\" style=\"color:rgb(199, 146, 234)\">]</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> entries </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> fs</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">readdirSync</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">directory</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> withFileTypes</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token boolean\" style=\"color:rgb(255, 88, 116)\">true</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  entries</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">forEach</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token parameter\">entry</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:rgb(127, 219, 202)\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> absolutePath </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> path</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">resolve</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">directory</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> entry</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">name</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token keyword control-flow\" style=\"color:rgb(127, 219, 202)\">if</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">entry</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">isDirectory</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// wow recursive 🐍</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">getPageFiles</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">absolutePath</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> files</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"> </span><span class=\"token keyword control-flow\" style=\"color:rgb(127, 219, 202)\">else</span><span class=\"token plain\"> </span><span class=\"token keyword control-flow\" style=\"color:rgb(127, 219, 202)\">if</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">isPageFile</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">absolutePath</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      files</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">push</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">absolutePath</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword control-flow\" style=\"color:rgb(127, 219, 202)\">return</span><span class=\"token plain\"> files</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\" style=\"display:inline-block\">\n</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">isPageFile</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token parameter\">filename</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword control-flow\" style=\"color:rgb(127, 219, 202)\">return</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    path</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">extname</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">filename</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">===</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'.html'</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">&amp;&amp;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">!</span><span class=\"token plain\">filename</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">endsWith</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'404.html'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span></div></pre><p>After I collect all absolute paths of HTML files, I pass them to <code>buildRSS</code> and <code>buildSitemap</code> and use <code>cheerio</code> to parse the content. (Learn more about <a href=\"https://cheerio.js.org/\" target=\"_blank\" rel=\"noopener noreferrer\">cheerio</a>) It is very unlikely that you can use the following code without modifying because how I use <code>cheerio</code> to parse the data is based on the HTML structure of my React components.</p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">buildRss</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token parameter\">pageFiles</span><span class=\"token parameter punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token parameter\"> pagesDir</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// use the reduce method to collect all RSS data</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> rssData </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> pageFiles</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">reduce</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token parameter\">data</span><span class=\"token parameter punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token parameter\"> file</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:rgb(127, 219, 202)\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// the pathname is the relative path from '/pages' to the HTML file</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> pathname </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> path</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">relative</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">pagesDir</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> file</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">slice</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">-</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'.html'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">length</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// collect all RSS top level info in the index page</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token keyword control-flow\" style=\"color:rgb(127, 219, 202)\">if</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">pathname </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">===</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'index'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> htmlString </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> fs</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">readFileSync</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">file</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'utf8'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> $ </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> cheerio</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">load</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">htmlString</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        data</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">title</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">$</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'title'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">text</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        data</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">home_page_url</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">$</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">meta[property='og:url']</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">attr</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'content'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        data</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">feed_url</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">$</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">          </span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">link[rel='alternate'][type='application/json']</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">attr</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'href'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        data</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">description</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">$</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">meta[name='description']</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">attr</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'content'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        data</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">icon</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">$</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">link[sizes='512x512']</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">attr</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'href'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        data</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">favicon</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">$</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">link[sizes='64x64']</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">attr</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'href'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// only add to RSS if the pathname is '/blog/*'</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token keyword control-flow\" style=\"color:rgb(127, 219, 202)\">if</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">pathname</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">startsWith</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'blog'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> htmlString </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> fs</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">readFileSync</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">file</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'utf8'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> $ </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> cheerio</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">load</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">htmlString</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// remove the placeholder image for lazy loading images</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">$</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">#Content img[aria-hidden='true']</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">remove</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        data</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">items</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">push</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">          url</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">$</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">meta[property='og:url']</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">attr</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'content'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">          id</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> pathname</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">substring</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'blog/'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">length</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">          content_html</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">$</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'#Content'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">html</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">          title</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">$</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'article h1'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">text</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">          summary</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">$</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">meta[name='description']</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">attr</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'content'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">          image</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">$</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">meta[property='og:image']</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">attr</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'content'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">          banner_image</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">$</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">meta[property='og:image']</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">attr</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'content'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">          date_published</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">$</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'time'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">attr</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'datetime'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">          author</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">            name</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">$</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">a[rel='author']</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">text</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">            url</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">$</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">a[rel='author']</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">attr</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'href'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">            avatar</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">$</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">img#Avatar</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">attr</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'src'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">          </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token keyword control-flow\" style=\"color:rgb(127, 219, 202)\">return</span><span class=\"token plain\"> data</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      version</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'https://jsonfeed.org/version/1'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      items</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">[</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">]</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// sort the items by the publishing date</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  rssData</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token property-access\">items</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">sort</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">byDateDesc</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// write to the output static folder</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  fs</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">writeFileSync</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    path</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">join</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'./.next/static'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'feed.json'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token known-class-name class-name\" style=\"color:rgb(255, 203, 139)\">JSON</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">stringify</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">rssData</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token keyword null nil\" style=\"color:rgb(127, 219, 202)\">null</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">2</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span></div></pre><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">buildSiteMap</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token parameter\">pageFiles</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// I am using the open graph URL tag as the url</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// but you can simply concat the base Url with the relative path</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> urls </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> pageFiles</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">map</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token parameter\">file</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:rgb(127, 219, 202)\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> htmlString </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> fs</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">readFileSync</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">file</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'utf8'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> $ </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> cheerio</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">load</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">htmlString</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token keyword control-flow\" style=\"color:rgb(127, 219, 202)\">return</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">$</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">meta[property='og:url']</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">attr</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'content'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> sitemap </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">&lt;urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\" </span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">  xmlns:news=\"http://www.google.com/schemas/sitemap-news/0.9\" </span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">  xmlns:xhtml=\"http://www.w3.org/1999/xhtml\" </span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">  xmlns:mobile=\"http://www.google.com/schemas/sitemap-mobile/1.0\" </span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">  xmlns:image=\"http://www.google.com/schemas/sitemap-image/1.1\" </span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">  xmlns:video=\"http://www.google.com/schemas/sitemap-video/1.1\"&gt;</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">  </span><span class=\"token template-string interpolation interpolation-punctuation punctuation\" style=\"color:rgb(199, 146, 234)\">${</span><span class=\"token template-string interpolation\">urls</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string interpolation\">    </span><span class=\"token template-string interpolation punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token template-string interpolation function\" style=\"color:rgb(130, 170, 255)\">map</span><span class=\"token template-string interpolation punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token template-string interpolation\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string interpolation\">      </span><span class=\"token template-string interpolation parameter\">url</span><span class=\"token template-string interpolation\"> </span><span class=\"token template-string interpolation operator\" style=\"color:rgb(127, 219, 202)\">=&gt;</span><span class=\"token template-string interpolation\"> `</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string interpolation\">    </span><span class=\"token template-string interpolation operator\" style=\"color:rgb(127, 219, 202)\">&lt;</span><span class=\"token template-string interpolation\">url</span><span class=\"token template-string interpolation operator\" style=\"color:rgb(127, 219, 202)\">&gt;</span><span class=\"token template-string interpolation\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string interpolation\">      </span><span class=\"token template-string interpolation operator\" style=\"color:rgb(127, 219, 202)\">&lt;</span><span class=\"token template-string interpolation\">loc</span><span class=\"token template-string interpolation operator\" style=\"color:rgb(127, 219, 202)\">&gt;</span><span class=\"token template-string interpolation\">$</span><span class=\"token template-string interpolation punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token template-string interpolation\">url</span><span class=\"token template-string interpolation punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token template-string interpolation operator\" style=\"color:rgb(127, 219, 202)\">&lt;</span><span class=\"token template-string interpolation operator\" style=\"color:rgb(127, 219, 202)\">/</span><span class=\"token template-string interpolation\">loc</span><span class=\"token template-string interpolation operator\" style=\"color:rgb(127, 219, 202)\">&gt;</span><span class=\"token template-string interpolation\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string interpolation\">      </span><span class=\"token template-string interpolation operator\" style=\"color:rgb(127, 219, 202)\">&lt;</span><span class=\"token template-string interpolation\">changefreq</span><span class=\"token template-string interpolation operator\" style=\"color:rgb(127, 219, 202)\">&gt;</span><span class=\"token template-string interpolation\">daily</span><span class=\"token template-string interpolation operator\" style=\"color:rgb(127, 219, 202)\">&lt;</span><span class=\"token template-string interpolation operator\" style=\"color:rgb(127, 219, 202)\">/</span><span class=\"token template-string interpolation\">changefreq</span><span class=\"token template-string interpolation operator\" style=\"color:rgb(127, 219, 202)\">&gt;</span><span class=\"token template-string interpolation\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string interpolation\">      </span><span class=\"token template-string interpolation operator\" style=\"color:rgb(127, 219, 202)\">&lt;</span><span class=\"token template-string interpolation\">priority</span><span class=\"token template-string interpolation operator\" style=\"color:rgb(127, 219, 202)\">&gt;</span><span class=\"token template-string interpolation number\" style=\"color:rgb(247, 140, 108)\">0.7</span><span class=\"token template-string interpolation operator\" style=\"color:rgb(127, 219, 202)\">&lt;</span><span class=\"token template-string interpolation operator\" style=\"color:rgb(127, 219, 202)\">/</span><span class=\"token template-string interpolation\">priority</span><span class=\"token template-string interpolation operator\" style=\"color:rgb(127, 219, 202)\">&gt;</span><span class=\"token template-string interpolation\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string interpolation\">    </span><span class=\"token template-string interpolation operator\" style=\"color:rgb(127, 219, 202)\">&lt;</span><span class=\"token template-string interpolation operator\" style=\"color:rgb(127, 219, 202)\">/</span><span class=\"token template-string interpolation\">url</span><span class=\"token template-string interpolation operator\" style=\"color:rgb(127, 219, 202)\">&gt;</span><span class=\"token template-string interpolation\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string interpolation\">    `</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string interpolation\">    </span><span class=\"token template-string interpolation punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token template-string interpolation\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string interpolation\">    </span><span class=\"token template-string interpolation punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token template-string interpolation function\" style=\"color:rgb(130, 170, 255)\">join</span><span class=\"token template-string interpolation punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token template-string interpolation string\" style=\"color:rgb(173, 219, 103)\">''</span><span class=\"token template-string interpolation punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token template-string interpolation interpolation-punctuation punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">  </span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">&lt;/urlset&gt;</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\"></span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  fs</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">writeFileSync</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">path</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">join</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'./.next/static'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'sitemap.xml'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> sitemap</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span></div></pre><p>Finally, here is the <code>vercel.json</code> routing configuration which you can learn more <a href=\"https://vercel.com/docs/configuration#routes\" target=\"_blank\" rel=\"noopener noreferrer\">here</a>.</p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">\"routes\"</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">[</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">\"src\"</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"/sitemap.xml\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">\"dest\"</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"/_next/static/sitemap.xml\"</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">\"src\"</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"/feed.json\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">\"dest\"</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"/_next/static/feed.json\"</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">]</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\" style=\"display:inline-block\">\n</span></div></pre><p>You can find the complete code in this <a href=\"https://gist.github.com/hangindev/dd11384cc79a54b6dc9646049b215d18\" target=\"_blank\" rel=\"noopener noreferrer\">gist</a>.</p><h2>Wrap up</h2><p>So there you have it, my hack(or not?) to put together the sitemap and RSS generation after countless trials and errors and googling. It relies on knowing the location of the output files in the Vercel environment which may change in the future as Next.js and Vercel update so keep an eye on it. This might not be the most straightforward method so please let me know your implementation. Thank you for reading. <em>Until next time! 👋</em></p><blockquote>I am redesigning my blog to integrate a CMS. (before that I used MDX to write my posts) I figured it's another good chance to learn new tech stacks. After playing with several headless CMSs, I picked <strong>Sanity.io</strong> to be used with my go-to SSG/SSR framework <strong>Next.js.</strong> I also tried out <strong>TailwindCSS</strong> to learn about what's going on with this trendy utility-first CSS. I will share my learning progress and tips I found regularly.</blockquote></div>",
      "title": "Generate Sitemap and RSS for Vercel Next.js App with Dynamic Routes",
      "summary": "In this article, I share how I create a sitemap and RSS for my Next.js blog. The tricky part is to deal with Next.js dynamic routes and serialize contents. Applicable if you are using MDX or CMS.",
      "image": "https://cdn.sanity.io/images/mus2e14o/production/233daa7d3dea3ad2d27b54d44d80ddf522423735-1200x630.jpg?w=1200&h=630",
      "banner_image": "https://cdn.sanity.io/images/mus2e14o/production/233daa7d3dea3ad2d27b54d44d80ddf522423735-1200x630.jpg?w=1200&h=630",
      "date_published": "2020-06-25T00:29:37Z",
      "author": {
        "name": "Jason Leung",
        "url": "https://twitter.com/hangindev",
        "avatar": "https://cdn.sanity.io/images/mus2e14o/production/6e3427d0324c88bbe86a0e0544f416779c4fc9e6-256x256.png?w=128"
      }
    },
    {
      "url": "https://hangindev.com/blog/create-a-custom-figure-block-in-sanity-that-supports-lazy-loading-effect",
      "id": "create-a-custom-figure-block-in-sanity-that-supports-lazy-loading-effect",
      "content_html": "<div><p>I recently integrated <strong>Sanity</strong> into my <strong>Next.js</strong> Blog and I wanted those <a href=\"https://using-gatsby-image.gatsbyjs.org/blur-up/\" target=\"_blank\" rel=\"noopener noreferrer\">gatsby-image</a> blur up effects for the images in my posts. While I was considering building my own image processing build steps, I found that Sanity image pipeline has already provided all the metadata that I needed. Sweet! 🍬 In this article, I will share how I created a custom <code>Figure</code> block in Sanity, and leverage its image pipeline to power my lazy loading image component. I will also show how I query the data I need with GROQ.</p><blockquote>In my last article, I shared what it takes to create an image with lazy loading effect and turned it into a React component. <a href=\"/blog/create-a-lazy-loading-image-component-with-react-hooks\">Read more</a> </blockquote><h2>Envision the Frontend Component 👁</h2><p>I am using React but you may implement it with Vue, Svelte, etc. The <code>&lt;LazyImage /&gt;</code> component takes 4 props: </p><ul><li><strong>src</strong> — <code>src</code> attribute for the <code>img</code> HTML element,</li><li><strong>alt</strong> — <code>alt</code> attribute for the <code>img</code> HTML element,</li><li><strong>lqip</strong> — stands for <em>L</em>ow-<em>Q</em>uality <em>I</em>mage <em>P</em>laceholder, can be a web URL or preferably, data URL,</li><li><strong>aspectRatio</strong> — to create an intrinsic placeholder to prevent reflows,</li><li><a href=\"https://codesandbox.io/s/create-a-lazy-loading-image-component-with-react-hooks-9hjbm?fontsize=14&amp;hidenavigation=1&amp;theme=dark\" target=\"_blank\" rel=\"noopener noreferrer\">Live demo</a></li></ul><p>I also want my images to be shown with a caption. That's why I created this <code>&lt;Figure /&gt;</code> component which is simply a <code>figure</code> element wrapped around the <code>&lt;LazyImage /&gt;</code> component and a conditionally rendered a <code>figcaption</code> element.</p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token function maybe-class-name\" style=\"color:rgb(130, 170, 255)\">Figure</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token parameter punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token parameter\"> alt</span><span class=\"token parameter punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token parameter\"> caption</span><span class=\"token parameter punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token parameter\"> captionUrl</span><span class=\"token parameter punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token parameter\"> src</span><span class=\"token parameter punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token parameter\"> lqip</span><span class=\"token parameter punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token parameter\"> aspectRatio </span><span class=\"token parameter punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword control-flow\" style=\"color:rgb(127, 219, 202)\">return</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">&lt;</span><span class=\"token plain\">figure</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">&lt;</span><span class=\"token maybe-class-name\">LazyImage</span><span class=\"token plain\"> alt</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\">alt</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"> src</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\">src</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"> lqip</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\">lqip</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"> aspectRatio</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\">aspectRatio</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">/</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\">caption </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">&amp;&amp;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">&lt;</span><span class=\"token plain\">figcaption</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">          </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\">captionUrl </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">?</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">            </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">&lt;</span><span class=\"token plain\">a href</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\">captionUrl</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"> target</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"_blank\"</span><span class=\"token plain\"> rel</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"noopener noreferrer\"</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">              </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\">caption</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">            </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">&lt;</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">/</span><span class=\"token plain\">a</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">          </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">            caption</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">          </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">&lt;</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">/</span><span class=\"token plain\">figcaption</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">&lt;</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">/</span><span class=\"token plain\">figure</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span></div></pre><h2>Mirror the Figure Type in Sanity 🗺️</h2><p>When you create a field with <code>image</code> type in Sanity and upload a photo to it, Sanity automatically populates several useful metadata such as an LQIP data URL, palette information, and the image dimension including aspect ratio which covers all the data we need to pass into the lazy loading image component.</p><p>To keep my content structured, I created a f<code>igure</code> type which is an <code>object</code> with 4 fields: </p><ul><li>image: <code>image</code> </li><li>alternate text: <code>string</code></li><li>caption: <code>string</code> </li><li>caption Url: <code>string</code></li></ul><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// figure.js</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:rgb(127, 219, 202)\">export</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:rgb(127, 219, 202)\">default</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  name</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'figure'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  type</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'object'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  title</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'Figure'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  fields</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">[</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      name</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'image'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      type</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'image'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      title</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'Image'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      options</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> metadata</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">[</span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'lqip'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">]</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      name</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'alt'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      type</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'string'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      title</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'Alternative Text'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      name</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'caption'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      type</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'string'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      title</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'Caption'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      name</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'captionUrl'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      type</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'string'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      title</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'Caption URL'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">]</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span></div></pre><p>I also specified that I want <code>lqip</code> to be generated from my images. Here you can find <a href=\"https://www.sanity.io/docs/image-type#example-of-a-image-asset-object-with-metadata-location-lqip-palette-and-dimensions-df3f768ce073\" target=\"_blank\" rel=\"noopener noreferrer\">a list of metadata</a> you can get. I then added it to the schema so that it can be reused as the type for other fields.</p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// schema.js</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">createSchema</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  name</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'default'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  types</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> schemaTypes</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">concat</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">[</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    link</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    internalLink</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    socailLink</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    portableText</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    simplePortableText</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    figure</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// 👈</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    video</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    post</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    author</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    blogSettings</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">]</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span></div></pre><p>To use this <code>figure</code> type for my portable texts, I added it to my <code>portableText</code> type. I will also use it for the <code>coverImage</code> field of the post <code>document</code>.</p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// portableText.js</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:rgb(127, 219, 202)\">export</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:rgb(127, 219, 202)\">default</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  title</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'Portable Text'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  name</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'portableText'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  type</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'array'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">of</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">[</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      type</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'block'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      styles</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">[</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> title</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'Normal'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> value</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'normal'</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> title</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'H2'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> value</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'h2'</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> title</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'H3'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> value</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'h3'</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> title</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'H4'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> value</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'h4'</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> title</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'Quote'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> value</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'blockquote'</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">]</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      marks</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        decorators</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">[</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">          </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> title</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'Strong'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> value</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'strong'</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">          </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> title</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'Emphasis'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> value</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'em'</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">          </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> title</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'Code'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> value</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'code'</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">]</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> type</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'figure'</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// 👈</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">]</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span></div></pre><p>Now I can go to the Sanity Studio and start using the newly added <code>figure</code> field.</p><figure class=\"text-center\"><div class=\"relative overflow-hidden md:rounded shadow-xl\"><div style=\"padding-bottom:66.66666666666667%\"></div><img loading=\"lazy\" class=\"absolute w-full h-full inset-0 object-cover object-center opacity-0 transition duration-700 ease-in-out transition-opacity\" src=\"https://cdn.sanity.io/images/mus2e14o/production/380548e80c64f09bad954bd35f444a5fb37ed2b9-1122x748.png\" alt=\"Custom figure field in Sanity\"></div><figcaption class=\"text-xs text-gray-800 mt-1\">Custom figure field in Sanity</figcaption></figure><h2>Query the Image Data</h2><p>To access the data from the application, I use Sanity's query language GROQ. Sanity does support deploying GraphQL APIs and <strong>it is tempting to do so</strong>. But I decided to stick with GROQ for a while and try to appreciate its design. </p><p>Below is the GROQ query for fetching all data for a post page. Notice how I transform all <code>figure</code> object which contains reference and nested object into a new object with only the fields I need. Yes, it looks gigantic... I am still learning so please let me know if there are ways to simplify it. 😉</p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">getPost</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token parameter\">slug</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword control-flow\" style=\"color:rgb(127, 219, 202)\">return</span><span class=\"token plain\"> client</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">fetch</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">/* groq */</span><span class=\"token plain\"> </span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">      *[_type == \"post\" &amp;&amp; slug.current == $slug] | order(_updatedAt desc) {</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">        title,</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">        publishedAt,</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">        excerpt,</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">        'slug': slug.current,</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">        'coverImage': { // 👈</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">          'alt': coverImage.alt,</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">          'src': coverImage.image.asset-&gt;url,</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">          'ext': coverImage.image.asset-&gt;extension,</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">          'lqip': coverImage.image.asset-&gt;metadata.lqip,</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">          'aspectRatio': coverImage.image.asset-&gt;metadata.dimensions.aspectRatio,</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">          'caption': coverImage.caption,</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">          'captionUrl': coverImage.captionUrl,</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">        },</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">        content[]{</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">          ...,</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">          _type == \"figure\" =&gt; { // 👈</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">             \"url\": @.image.asset-&gt;url,       </span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">             \"lqip\": @.image.asset-&gt;metadata.lqip,</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">             \"aspectRatio\": @.image.asset-&gt;metadata.dimensions.aspectRatio, </span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">          },</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">          markDefs[]{</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">            ...,</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">            _type == \"internalLink\" =&gt; { </span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">              'type': @-&gt;_type,</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">              'slug': @-&gt;slug.current,</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">            }</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">          }</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">        },</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">      }[0]</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">    </span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> slug </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span></div></pre><h2>Thoughts</h2><p>Creating a custom block/field feels pretty straight forward to me using Sanity. The challenging part is to query/transform/join data. I am aware that I have been using just a tiny fraction of what Sanity has offered and I am excited to see what I can build with it. </p><p>I will write about my learning progress and other tips here. Please follow my <a href=\"https://twitter.com/hangindev\" target=\"_blank\" rel=\"noopener noreferrer\">Twitter</a> or <a href=\"https://dev.to/hangindev\" target=\"_blank\" rel=\"noopener noreferrer\">DEV</a> account to get the latest updates. <em>Ciao!</em></p><h5><a href=\"https://twitter.com/hangindev/status/1275050877384929281\" target=\"_blank\" rel=\"noopener noreferrer\">Discuss on Twitter</a></h5><blockquote>I am redesigning my blog to integrate a CMS. (before that I used MDX to write my posts) I figured it's another good chance to learn new tech stacks. After playing with several headless CMSs, I picked <strong>Sanity.io</strong> to be used with my go-to SSG/SSR framework <strong>Next.js.</strong> I also tried out <strong>TailwindCSS</strong> to learn about what's going on with this trendy utility-first CSS. I will share my learning progress and tips I found regularly.</blockquote></div>",
      "title": "Create a Custom Figure Block in Sanity that Supports Lazy Loading Effect",
      "summary": "In this article, I will share how I created a custom figure block in Sanity, and leverage its image pipeline to power my lazy loading image component.",
      "image": "https://cdn.sanity.io/images/mus2e14o/production/71f6b7aa3ef997950aa20da36cfbacb2712de5d5-1200x630.jpg?w=1200&h=630",
      "banner_image": "https://cdn.sanity.io/images/mus2e14o/production/71f6b7aa3ef997950aa20da36cfbacb2712de5d5-1200x630.jpg?w=1200&h=630",
      "date_published": "2020-06-22T02:35:41Z",
      "author": {
        "name": "Jason Leung",
        "url": "https://twitter.com/hangindev",
        "avatar": "https://cdn.sanity.io/images/mus2e14o/production/6e3427d0324c88bbe86a0e0544f416779c4fc9e6-256x256.png?w=128"
      }
    },
    {
      "url": "https://hangindev.com/blog/create-a-lazy-loading-image-component-with-react-hooks",
      "id": "create-a-lazy-loading-image-component-with-react-hooks",
      "content_html": "<div><p>Lazy-loading images (like those in Medium or those created by <em>gatsby-image </em>🧡) can sometimes add an extra touch of style to a page. To create such an effect, one will need A) a tiny version of the image for preview, ideally inlined as data URL, and B) the aspect ratio of the image to create a placeholder to prevent reflows. In this article, I will share how I created a lazy-loading image component with React Hooks.</p><p><strong><a href=\"https://codesandbox.io/s/create-a-lazy-loading-image-component-with-react-hooks-9hjbm?fontsize=14&amp;hidenavigation=1&amp;theme=dark\" target=\"_blank\" rel=\"noopener noreferrer\">CodeSandbox Demo</a></strong></p><h2>First, the barebone - HTML/CSS 🦴</h2><p>Usually, a lazing loading image consists of 4 HTML Elements:</p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">class</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">wrapper</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag style-attr attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">style</span><span class=\"token tag style-attr attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag style-attr attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag style-attr attr-value style language-css property\" style=\"color:rgb(128, 203, 196)\">padding-bottom</span><span class=\"token tag style-attr attr-value style language-css punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token tag style-attr attr-value style language-css number\" style=\"color:rgb(247, 140, 108)\">56.25</span><span class=\"token tag style-attr attr-value style language-css unit\" style=\"color:rgb(127, 219, 202)\">%</span><span class=\"token tag style-attr attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"> </span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">img</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">    </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">src</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAUACYDASIAAhEBAxEB/8QAGQABAAMBAQAAAAAAAAAAAAAAAAQGBwEF/8QALhAAAgEDAgQEBAcAAAAAAAAAAQIDAAQRBRIGITFBBxMikTJRgbEVFkJhYnGh/8QAFgEBAQEAAAAAAAAAAAAAAAAABAMC/8QAHhEAAgICAgMAAAAAAAAAAAAAAAIBAxESITEyM1H/2gAMAwEAAhEDEQA/AKdpOiaOHUvYzs2wJkZwB860Dg/QbKxvIntLZkLyB2Dsctjn3qPZ6JqDoRHPatjphtpHuKi8TaxJwzabblliunOEO4MCRjv9aKuWbECZ1WMlz8QdJGu2MrpBDaX1uoeKbzAQe+04+/Y1n35cW5tUubGdkWT48+rDd/8Aar3F3G9xqkCx2mYIgm2RlyDI3T2PXlUHw/1S/E2oWspmWJlEkLHKq20AMA3TuOVVsqbTJiHSW1JGqcIzysQ1yylXOCUxkUr0bi6uJG3Sv8PpCh8/WlRiW+mtENe06OMBB5antzH7VmvjnaRbbaQAq8YAUj+XI/YUpSa/Ii/RXNI0Kxn8Fte1x4z+J2N5EkMwPRSUBGOn6z7D5VbdFUbEhb1RhgmG59uZ/ulKdVyjg7vZWdvNJtJcF4+eTzHKlKUAcf/Z</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">  </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">/&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">img</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">    </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">src</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">https://images.unsplash.com/photo-1518991791750-044b923256f0?fit=crop&amp;w=1200&amp;h=630</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">    </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">class</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">source</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">  </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">/&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span></div></pre><ol><li>a relatively positioned wrapper <code>div</code>, </li><li>an intrinsic placeholder <code>div</code> for maintaining aspect ratio. It has <code>padding-bottom</code> with a percentage value(relative to the <em>width</em> of the containing block), e.g. for a 16:9 image, the percentage is calculated as 9/16 * 100% = 56.25%,</li><li>an absolutely positioned <code>img</code> for the tiny version of the image, also known as LQIP(<strong>L</strong>ow-<strong>Q</strong>uality <strong>I</strong>mage <strong>P</strong>laceholder), stretched to cover the wrapper. Data URL is usually used as the <code>src</code> to save HTTP requests,</li><li>an absolutely positioned <code>img</code> for the source image, placed on top of the LQIP, initialized with <code>opacity: 0</code>.</li></ol><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token selector class\" style=\"color:rgb(199, 146, 234);font-style:italic\">.wrapper</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">position</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token plain\"> relative</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">overflow</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token plain\"> hidden</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token selector\" style=\"color:rgb(199, 146, 234);font-style:italic\">img</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">position</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token plain\"> absolute</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">width</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">100</span><span class=\"token unit\">%</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">height</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">100</span><span class=\"token unit\">%</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">top</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">bottom</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">left</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">right</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">object-fit</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token plain\"> cover</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">object-position</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token plain\"> center</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token selector class\" style=\"color:rgb(199, 146, 234);font-style:italic\">.source</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">opacity</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">0</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">transition</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token plain\"> opacity </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">1</span><span class=\"token unit\">s</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token selector class\" style=\"color:rgb(199, 146, 234);font-style:italic\">.loaded</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token property\" style=\"color:rgb(128, 203, 196)\">opacity</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">1</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span></div></pre><h2>Turn it into React Component ⚛</h2><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">import</span><span class=\"token plain\"> React</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> useState</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> useEffect</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> useRef </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"react\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">import</span><span class=\"token plain\"> clsx </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">\"clsx\"</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"> </span><span class=\"token comment\" style=\"color:rgb(99, 119, 119);font-style:italic\">// a utility for constructing className conditionally</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\" style=\"display:inline-block\">\n</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">LazyImage</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token parameter punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token parameter\"> className</span><span class=\"token parameter punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token parameter\"> src</span><span class=\"token parameter punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token parameter\"> alt</span><span class=\"token parameter punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token parameter\"> lqip</span><span class=\"token parameter punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token parameter\"> aspectRatio </span><span class=\"token parameter operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token parameter\"> </span><span class=\"token parameter number\" style=\"color:rgb(247, 140, 108)\">2</span><span class=\"token parameter operator\" style=\"color:rgb(127, 219, 202)\">/</span><span class=\"token parameter number\" style=\"color:rgb(247, 140, 108)\">3</span><span class=\"token parameter\"> </span><span class=\"token parameter punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">[</span><span class=\"token plain\">loaded</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> setLoaded</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">useState</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token boolean\" style=\"color:rgb(255, 88, 116)\">false</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> imgRef </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">useRef</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">useEffect</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">if</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">imgRef</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token plain\">current </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">&amp;&amp;</span><span class=\"token plain\"> imgRef</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token plain\">current</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token plain\">complete</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">setLoaded</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token boolean\" style=\"color:rgb(255, 88, 116)\">true</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">[</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">]</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">return</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">className</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token tag script language-javascript function\" style=\"color:rgb(130, 170, 255)\">clsx</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token tag script language-javascript string\" style=\"color:rgb(173, 219, 103)\">\"wrapper\"</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token tag script language-javascript\" style=\"color:rgb(127, 219, 202)\"> className</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">style</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token tag script language-javascript\" style=\"color:rgb(127, 219, 202)\"> paddingBottom</span><span class=\"token tag script language-javascript operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token tag script language-javascript\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag script language-javascript template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token tag script language-javascript template-string interpolation interpolation-punctuation punctuation\" style=\"color:rgb(199, 146, 234)\">${</span><span class=\"token tag script language-javascript template-string interpolation number\" style=\"color:rgb(247, 140, 108)\">100</span><span class=\"token tag script language-javascript template-string interpolation\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag script language-javascript template-string interpolation operator\" style=\"color:rgb(127, 219, 202)\">/</span><span class=\"token tag script language-javascript template-string interpolation\" style=\"color:rgb(127, 219, 202)\"> aspectRatio</span><span class=\"token tag script language-javascript template-string interpolation interpolation-punctuation punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token tag script language-javascript template-string string\" style=\"color:rgb(173, 219, 103)\">%</span><span class=\"token tag script language-javascript template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token tag script language-javascript\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">/&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">img</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">src</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token tag script language-javascript\" style=\"color:rgb(127, 219, 202)\">lqip</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">aria-hidden</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">true</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">/&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">      </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">img</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">        </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">loading</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag attr-value\" style=\"color:rgb(127, 219, 202)\">lazy</span><span class=\"token tag attr-value punctuation\" style=\"color:rgb(199, 146, 234)\">\"</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">        </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">src</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token tag script language-javascript\" style=\"color:rgb(127, 219, 202)\">src</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">        </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">alt</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token tag script language-javascript\" style=\"color:rgb(127, 219, 202)\">alt</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">        </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">ref</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token tag script language-javascript\" style=\"color:rgb(127, 219, 202)\">imgRef</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">        </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">onLoad</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token tag script language-javascript\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag script language-javascript operator\" style=\"color:rgb(127, 219, 202)\">=&gt;</span><span class=\"token tag script language-javascript\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag script language-javascript function\" style=\"color:rgb(130, 170, 255)\">setLoaded</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token tag script language-javascript boolean\" style=\"color:rgb(255, 88, 116)\">true</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">        </span><span class=\"token tag attr-name\" style=\"color:rgb(173, 219, 103);font-style:italic\">className</span><span class=\"token tag script language-javascript script-punctuation punctuation\" style=\"color:rgb(199, 146, 234)\">=</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token tag script language-javascript function\" style=\"color:rgb(130, 170, 255)\">clsx</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token tag script language-javascript string\" style=\"color:rgb(173, 219, 103)\">\"source\"</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token tag script language-javascript\" style=\"color:rgb(127, 219, 202)\"> loaded </span><span class=\"token tag script language-javascript operator\" style=\"color:rgb(127, 219, 202)\">&amp;&amp;</span><span class=\"token tag script language-javascript\" style=\"color:rgb(127, 219, 202)\"> </span><span class=\"token tag script language-javascript string\" style=\"color:rgb(173, 219, 103)\">\"loaded\"</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token tag script language-javascript punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">      </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">/&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&lt;/</span><span class=\"token tag\" style=\"color:rgb(127, 219, 202)\">div</span><span class=\"token tag punctuation\" style=\"color:rgb(199, 146, 234)\">&gt;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">export</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">default</span><span class=\"token plain\"> LazyImage</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span></div></pre><p>Let's break it down: there is a <code>loaded</code> state to track the loading state of the souce image, initialized to be <code>false</code>. A \"load\" event listener is added to the source <code>img</code> element so when it finishes loading, the state is updated and a \"loaded\" class name is appended to its class list which sets its opacity to 1. In cases which <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/complete\" target=\"_blank\" rel=\"noopener noreferrer\">the source image has completely loaded</a> before this component is mounted, the newly added \"load\" event listener will never fire. That's why a ref is also passed to the <code>img</code> element for checking its complete attribute on mount, and update the state accordingly.</p><p>A <code>loading=\"lazy\"</code> attribute is added to the source <code>img</code> to tell the browser to load the image immediately if it is in the viewport, or to fetch it when the user scrolls near it. More about that in this <a href=\"https://web.dev/lazy-loading-images/\" target=\"_blank\" rel=\"noopener noreferrer\">web.dev article</a>. I also added <code>aria-hidden=\"true\"</code> to the LQIP img to <a href=\"https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-hidden_attribute\" target=\"_blank\" rel=\"noopener noreferrer\">hide it from the accessibility API</a>.</p><h2>Usage</h2><p>To use this component, you'll have to generate the image LQIP and get its aspect ratio. There are libraries that help you to integrate the generation into your build process, for example, <a href=\"https://github.com/zouhir/lqip\" target=\"_blank\" rel=\"noopener noreferrer\">zouhir/lqip</a>. Apparently, if you're using Cloudindary, you can <a href=\"https://cloudinary.com/blog/low_quality_image_placeholders_lqip_explained\" target=\"_blank\" rel=\"noopener noreferrer\">create LQIP</a> through their image transformation pipeline.  But I suspect you can only get a regular URL instead of data URL or base64 so you might have to convert it yourself if you want to inline it. </p><p>In previous projects, I used <code>sharp</code>(a high-performance image processing module<code>)</code> in Next.js <code>getStaticProps</code> (a function that runs at build time for static generation) to help me populating those image data.  Below is the function that I used:</p><pre style=\"color:#d6deeb;background-color:#011627\" class=\"text-sm\"><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token keyword module\" style=\"color:rgb(127, 219, 202)\">import</span><span class=\"token plain\"> </span><span class=\"token imports\">got</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:rgb(127, 219, 202)\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'got'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token keyword module\" style=\"color:rgb(127, 219, 202)\">import</span><span class=\"token plain\"> </span><span class=\"token imports\">sharp</span><span class=\"token plain\"> </span><span class=\"token keyword module\" style=\"color:rgb(127, 219, 202)\">from</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'sharp'</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\" style=\"display:inline-block\">\n</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">sharp</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">cache</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token boolean\" style=\"color:rgb(255, 88, 116)\">false</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\" style=\"display:inline-block\">\n</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">async</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">generateLazyImage</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token parameter\">src</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> body </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword control-flow\" style=\"color:rgb(127, 219, 202)\">await</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">got</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">src</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> responseType</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'buffer'</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> sharpImage </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:rgb(130, 170, 255)\">sharp</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token plain\">body</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> width</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> height</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> format </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword control-flow\" style=\"color:rgb(127, 219, 202)\">await</span><span class=\"token plain\"> sharpImage</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">metadata</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:rgb(127, 219, 202)\">const</span><span class=\"token plain\"> lqipBuf </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword control-flow\" style=\"color:rgb(127, 219, 202)\">await</span><span class=\"token plain\"> sharpImage</span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">resize</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"> width</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">30</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> height</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:rgb(247, 140, 108)\">30</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"> fit</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:rgb(173, 219, 103)\">'inside'</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token method function property-access\" style=\"color:rgb(130, 170, 255)\">toBuffer</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token keyword control-flow\" style=\"color:rgb(127, 219, 202)\">return</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">{</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    src</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    aspectRatio</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> width </span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">/</span><span class=\"token plain\"> height</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">    lqip</span><span class=\"token operator\" style=\"color:rgb(127, 219, 202)\">:</span><span class=\"token plain\"> </span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">data:image/</span><span class=\"token template-string interpolation interpolation-punctuation punctuation\" style=\"color:rgb(199, 146, 234)\">${</span><span class=\"token template-string interpolation\">format</span><span class=\"token template-string interpolation interpolation-punctuation punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token template-string string\" style=\"color:rgb(173, 219, 103)\">;base64,</span><span class=\"token template-string interpolation interpolation-punctuation punctuation\" style=\"color:rgb(199, 146, 234)\">${</span><span class=\"token template-string interpolation\">lqipBuf</span><span class=\"token template-string interpolation punctuation\" style=\"color:rgb(199, 146, 234)\">.</span><span class=\"token template-string interpolation function\" style=\"color:rgb(130, 170, 255)\">toString</span><span class=\"token template-string interpolation punctuation\" style=\"color:rgb(199, 146, 234)\">(</span><span class=\"token template-string interpolation string\" style=\"color:rgb(173, 219, 103)\">'base64'</span><span class=\"token template-string interpolation punctuation\" style=\"color:rgb(199, 146, 234)\">)</span><span class=\"token template-string interpolation interpolation-punctuation punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token template-string template-punctuation string\" style=\"color:rgb(173, 219, 103)\">`</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">,</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">;</span><span class=\"token plain\"></span></div><div class=\"token-line\" style=\"color:#d6deeb\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:rgb(199, 146, 234)\">}</span></div></pre><p>That's it! The <code>&lt;LazyImage /&gt;</code> is a pretty simple component that I use in almost all of my projects. Let me know your thoughts and how you present images on your sites. 😉</p><p>Please follow my Twitter account if you want to read my future posts. I promise I will figure out how to do RSS with Next.js soon...🔜</p><h5><a href=\"https://twitter.com/hangindev/status/1274564022373740545\" target=\"_blank\" rel=\"noopener noreferrer\">Discuss on Twitter</a></h5><blockquote>I am redesigning my blog to integrate a CMS. (before that I used MDX to write my posts) I figured it's another good chance to learn new tech stacks. After playing with several headless CMSs, I picked <strong>Sanity.io</strong> to be used with my go-to SSG/SSR framework <strong>Next.js.</strong> I also tried out <strong>TailwindCSS</strong> to learn about what's going on with this trendy utility-first CSS. I will share my learning progress and tips I found regularly.</blockquote></div>",
      "title": "Create a Lazy-Loading Image Component with React Hooks",
      "summary": " In this article, I will share what it takes to create a lazy loading image effect and how I created a LazyImage component in React.",
      "image": "https://cdn.sanity.io/images/mus2e14o/production/0cd3e86ccc7036aa812fbd8dd2d979e9b41bc172-1200x630.jpg?w=1200&h=630",
      "banner_image": "https://cdn.sanity.io/images/mus2e14o/production/0cd3e86ccc7036aa812fbd8dd2d979e9b41bc172-1200x630.jpg?w=1200&h=630",
      "date_published": "2020-06-21T01:01:35Z",
      "author": {
        "name": "Jason Leung",
        "url": "https://twitter.com/hangindev",
        "avatar": "https://cdn.sanity.io/images/mus2e14o/production/6e3427d0324c88bbe86a0e0544f416779c4fc9e6-256x256.png?w=128"
      }
    }
  ],
  "title": "A Blog by Hangindev",
  "home_page_url": "https://hangindev.com",
  "feed_url": "https://hangindev.com/feed.json",
  "description": "A Blog by Hangindev",
  "icon": "https://cdn.sanity.io/images/mus2e14o/production/2bec364282336aaad8e7a887e4b40904937174f6-256x256.png?w=512&h=512",
  "favicon": "https://cdn.sanity.io/images/mus2e14o/production/2bec364282336aaad8e7a887e4b40904937174f6-256x256.png?w=64&h=64",
  "author": {
    "name": "Jason Leung",
    "url": "https://twitter.com/hangindev",
    "avatar": "https://cdn.sanity.io/images/mus2e14o/production/6e3427d0324c88bbe86a0e0544f416779c4fc9e6-256x256.png?w=128"
  }
}