<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Andrii Shupta</title>
    <description>The latest articles on DEV Community by Andrii Shupta (@andriishupta).</description>
    <link>https://dev.to/andriishupta</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F687483%2Fbc1fe17b-d22a-4196-9c6c-0316ccab8f87.png</url>
      <title>DEV Community: Andrii Shupta</title>
      <link>https://dev.to/andriishupta</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/andriishupta"/>
    <language>en</language>
    <item>
      <title>Connect Polkadot to a Next.js website with @polkadot/extension-dapp</title>
      <dc:creator>Andrii Shupta</dc:creator>
      <pubDate>Sat, 17 Dec 2022 09:34:11 +0000</pubDate>
      <link>https://dev.to/andriishupta/connect-polkadot-to-a-nextjs-website-with-polkadotextension-dapp-55d1</link>
      <guid>https://dev.to/andriishupta/connect-polkadot-to-a-nextjs-website-with-polkadotextension-dapp-55d1</guid>
      <description>&lt;h2&gt;
  
  
  🔗 Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/andriishupta" rel="noopener noreferrer"&gt;andriishupta/polkadot-extension-dapp-example | GitHub&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://polkadot-extension-dapp-example.vercel.app" rel="noopener noreferrer"&gt;polkadot-extension-dapp-example | Deployed on Vercel&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://polkadot.js.org/docs/extension/" rel="noopener noreferrer"&gt;Extension Docs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://subwallet.app/" rel="noopener noreferrer"&gt;SubWallet&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/dappforce/polkaverse" rel="noopener noreferrer"&gt;PolkaVerse | GitHub&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/andriishupta/subtips-app" rel="noopener noreferrer"&gt;Subtips | Github&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;🌴 &lt;a href="https://linktr.ee/andriishupta" rel="noopener noreferrer"&gt;My Links&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📰 Published on
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://blog.andriishupta.dev" rel="noopener noreferrer"&gt;Hashnode 💻&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://andriishupta.medium.com" rel="noopener noreferrer"&gt;Medium ✍️&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/andriishupta"&gt;DEV Community 👩‍💻👨‍💻&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🤓 Intro
&lt;/h2&gt;

&lt;p&gt;As a developer, it's essential to understand the differences between various blockchain platforms to choose the right one for your needs. One key difference(as for me) is the availability of technical resources and tutorials for developers. Ethereum has many articles and tutorials demonstrating how to connect a wallet to a website, whereas there is less information available on Polkadot. This may make it easier for developers who are new to Ethereum to get started and learn how to build applications on the platform.&lt;/p&gt;

&lt;p&gt;It's important for developers also to be familiar with Polkadot and how to build on its platform, as it has unique features and potential applications.&lt;/p&gt;

&lt;p&gt;Developer Experience outside just documentation is quite important nowadays for the web3 community.&lt;/p&gt;

&lt;p&gt;In this article, I will show an example of how to connect a &lt;a href="https://subwallet.app" rel="noopener noreferrer"&gt;SubWallet&lt;/a&gt;(that's what I have used) to a Next.js website.&lt;/p&gt;

&lt;h3&gt;
  
  
  Technology
&lt;/h3&gt;

&lt;p&gt;On Ethereum, we have web3.js and ethers.js for connecting to a website and many different libraries built on top of it. For example, many projects I have seen use &lt;a href="https://wagmi.sh/" rel="noopener noreferrer"&gt;wagmi&lt;/a&gt; with React.js. It is just a blessing, such as it includes a full list of functionality that you need to have to interact with blockchain: "Connect Wallet" display ENS and balances information, sign messages, interact with contracts, and much more — all with caching, request deduplication, and persistence.&lt;/p&gt;

&lt;p&gt;Polkadot has production-ready libraries and tools to work with blockchain, and one of them is &lt;code&gt;@polkadot/extension-dapp&lt;/code&gt;. That's what we would use to "Connect Wallet".&lt;/p&gt;

&lt;h2&gt;
  
  
  🧑‍💻 Coding
&lt;/h2&gt;

&lt;p&gt;We will use the default Next.js app, so nothing is new here. Check out &lt;a href="https://nextjs.org/docs/getting-started" rel="noopener noreferrer"&gt;Getting Started&lt;/a&gt; to remind yourself of Next.js.&lt;/p&gt;

&lt;p&gt;The most crucial point with &lt;code&gt;@polkadot/extension-dapp&lt;/code&gt; is that it needs a browser to run, so with Next.js, we need to render the "Connect" button only during Client-Side rendering. For that, we would use &lt;a href="https://nextjs.org/docs/advanced-features/dynamic-import" rel="noopener noreferrer"&gt;dynamic import&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/andriishupta/polkadot-extension-dapp-example/blob/main/pages/index.tsx" rel="noopener noreferrer"&gt;🔗 source code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flrwtydlet4m0p9w3egbh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flrwtydlet4m0p9w3egbh.png" alt="dynamic-import" width="800" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the Home page, we load our &lt;code&gt;Connect&lt;/code&gt; component dynamically. Connect components are where all magic happens.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/andriishupta/polkadot-extension-dapp-example/blob/main/components/Connect.tsx" rel="noopener noreferrer"&gt;🔗 source code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's start with imports:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0lc5sipgup7d80j83h9f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0lc5sipgup7d80j83h9f.png" alt="polkadot-imports" width="800" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;InjectedAccountWithMeta&lt;/code&gt; is a type of account that we would get. I imported it for TypeScript.&lt;/p&gt;

&lt;p&gt;Our main focus here is &lt;code&gt;web3Enable&lt;/code&gt; and &lt;code&gt;web3Accounts&lt;/code&gt; .&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I have used promise chaining down below, but if you prefer&lt;/em&gt; &lt;code&gt;try-catch&lt;/code&gt; &lt;em&gt;+&lt;/em&gt; &lt;code&gt;async / await&lt;/code&gt; &lt;em&gt;- go for it!&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;web3Enable&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7wcqnnbwntezoj01m67.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7wcqnnbwntezoj01m67.png" alt="web3Enable" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The initial function is to call even to check if our browser has any wallets to work with. In case we don't have anything to work with, the extension shows it in the console, and we also should throw an error to show the user that he should use the browser with a valid Wallet.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;web3Accounts&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fixohuzesqlzn71wj4gdr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fixohuzesqlzn71wj4gdr.png" alt="web3Accounts" width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Same with &lt;code&gt;web3Accounts&lt;/code&gt; - it would load accounts connected or prompt you to connect to the website if you opened it for the first time - a very familiar experience for web3 users.&lt;/p&gt;

&lt;p&gt;You could try out the flow on &lt;a href="https://polkadot-extension-dapp-example.vercel.app" rel="noopener noreferrer"&gt;polkadot-extension-dapp-example | Deployed on Vercel&lt;/a&gt;, and it looks like this:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: I have tried only when I have 1 wallet, but for a simple example, it should be enough.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgsy7gbl9mfbn00ny8jle.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgsy7gbl9mfbn00ny8jle.png" alt="connect" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0kf28do3g6lhoc7a5qoe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0kf28do3g6lhoc7a5qoe.png" alt="connecting" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdjodd1a889oif47fgsed.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdjodd1a889oif47fgsed.png" alt="hello" width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe7ihis37zzvgo1bvhncw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe7ihis37zzvgo1bvhncw.png" alt="error" width="800" height="317"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmgdgdp9yqszxd9ejzxjd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmgdgdp9yqszxd9ejzxjd.png" alt="logs" width="800" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🧑‍🏫 Next steps and more examples
&lt;/h2&gt;

&lt;p&gt;With a connected wallet and available account, you can do everything you want: check out how to create and sign a transaction, show &lt;code&gt;&amp;lt;Identicon/&amp;gt;&lt;/code&gt; and more:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://polkadot.js.org/docs" rel="noopener noreferrer"&gt;https://polkadot.js.org/docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A more mature example using &lt;code&gt;@polkadot/api&lt;/code&gt; , &lt;code&gt;@polkadot/ui-keyring&lt;/code&gt; and more is &lt;a href="https://github.com/dappforce/polkaverse" rel="noopener noreferrer"&gt;PolkaVerse&lt;/a&gt;. It is a decentralized social network built on &lt;a href="https://subsocial.network/" rel="noopener noreferrer"&gt;Subsocial&lt;/a&gt; - "The Blockchain for Social Finance".&lt;/p&gt;

&lt;p&gt;Also, I have another project where I tried to use Subsocial API - it is raw-raw-raw cause it was fine for me to connect to Subsocial API and Polkadot to experience how things work. Feel free to check it out: &lt;a href="https://github.com/andriishupta/subtips-app" rel="noopener noreferrer"&gt;https://github.com/andriishupta/subtips-app&lt;/a&gt;&lt;/p&gt;










&lt;p&gt;Thanks for reading! 🙇&lt;/p&gt;

</description>
      <category>polkadot</category>
      <category>web3</category>
      <category>nextjs</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Simplify usage of Lens API with @use-lens and graphql-codegen</title>
      <dc:creator>Andrii Shupta</dc:creator>
      <pubDate>Tue, 04 Oct 2022 11:05:21 +0000</pubDate>
      <link>https://dev.to/andriishupta/simplify-usage-of-lens-api-with-use-lens-and-graphql-codegen-5fk1</link>
      <guid>https://dev.to/andriishupta/simplify-usage-of-lens-api-with-use-lens-and-graphql-codegen-5fk1</guid>
      <description>&lt;h2&gt;
  
  
  🔗 Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/andriishupta" rel="noopener noreferrer"&gt;andriishupta | Github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/use-lens/use-lens" rel="noopener noreferrer"&gt;Use Lens | Github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.lens.xyz" rel="noopener noreferrer"&gt;Lens API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://the-guild.dev/graphql/codegen" rel="noopener noreferrer"&gt;GraphQL Code Generator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📰 Published on
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.andriishupta.dev" rel="noopener noreferrer"&gt;Hashnode 💻&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://andriishupta.medium.com" rel="noopener noreferrer"&gt;Medium ✍️&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/andriishupta"&gt;DEV Community 👩‍💻👨‍💻&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🤓 Intro
&lt;/h2&gt;

&lt;p&gt;Recently, I have used Lens API to build some playground apps and noticed a repetitive task: I created Lens API Queries and Mutations for every project and used &lt;a href="https://the-guild.dev/graphql/codegen" rel="noopener noreferrer"&gt;GraphQL Code Generator&lt;/a&gt; to use React hooks with Apollo Client. &lt;/p&gt;

&lt;p&gt;After 2nd time doing the same job, I decided to create a library for easier use of Lens API that would save me some time to do actual work.&lt;/p&gt;

&lt;p&gt;I have never created open-source packages and thought it would be a great experience to do it, even if only I would use it 😅.&lt;/p&gt;

&lt;p&gt;npm &lt;a href="https://www.npmjs.com/org/use-lens" rel="noopener noreferrer"&gt;@use-lens&lt;/a&gt; so far contains 2 packages - &lt;em&gt;CLI&lt;/em&gt; and &lt;em&gt;react-apollo&lt;/em&gt;. Later in this article, I will explain how to use them and when, and the same information could be found in the &lt;a href="https://github.com/use-lens/use-lens/#-usage" rel="noopener noreferrer"&gt;repo's README.md&lt;/a&gt;.&lt;br&gt;
I will explain how I see the best use of &lt;code&gt;@use-lens/*&lt;/code&gt; later in the article.&lt;/p&gt;

&lt;p&gt;Also, I liked Lens Protocol so much that I have created Github Organization &lt;a href="https://github.com/use-lens" rel="noopener noreferrer"&gt;Use Lens&lt;/a&gt;, where I plan to develop and publish some tools, examples and apps working on top of Lens.&lt;/p&gt;
&lt;h3&gt;
  
  
  Technology
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Lens Protocol is a composable and decentralized social graph, ready for you to build on so you can focus on creating a great experience, not scaling your users.&lt;/p&gt;

&lt;p&gt;Own your content. Own your social graph. Own your data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you have read so far - you know what Lens API is and how to use it. If you are here to check out &lt;code&gt;@use-lens&lt;/code&gt; or just to check how to generate GraphQL code - educate yourself of Lens Protocol and API here:&lt;/p&gt;

&lt;p&gt;🌿 &lt;a href="https://docs.lens.xyz" rel="noopener noreferrer"&gt;https://docs.lens.xyz&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://the-guild.dev/graphql/codegen" rel="noopener noreferrer"&gt;GraphQL Code Generator&lt;/a&gt; - is a tool to build read-to-use code from your GraphQL schema and operations with a simple CLI with a lot of plugins for different frameworks: React, Next.js, Svelte, Vue with Apollo, URLQ and others - you name it.&lt;/p&gt;
&lt;h2&gt;
  
  
  🧑‍💻 How to
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Generate with &lt;a href="https://github.com/use-lens/use-lens/tree/main/packages/cli" rel="noopener noreferrer"&gt;@use-lens/cli&lt;/a&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @use-lens/cli
use-lens generate %PACKAGE%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;with &lt;code&gt;npx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @use-lens/cli generate %PACKAGE%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This would copy essential files of Lens API to your repo and would run &lt;code&gt;graphql-codegen&lt;/code&gt; to generate the code. By default, it would go to &lt;code&gt;src/lens-api/index.ts&lt;/code&gt;.&lt;br&gt;
From here, you could adjust &lt;code&gt;tsconfig.json&lt;/code&gt; to use it with &lt;code&gt;@use-lens&lt;/code&gt; shortening, so it would feel like a package usage. More on how to do it &lt;a href="https://github.com/use-lens/use-lens/tree/main/packages/cli#optional-tsconfigs-paths" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  With &lt;code&gt;@use-lens/*&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The simple &lt;code&gt;npm install --save @use-lens/%PACKAGE%&lt;/code&gt; and use it as a regular package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;GlobalProtocolStatsDocument&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;GlobalProtocolStats&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;GlobalProtocolStatsType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useGlobalProtocolStatsQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useGlobalProtocolStatsLazyQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@use-lens/react-apollo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Manual GraphQL Code Generator
&lt;/h3&gt;

&lt;p&gt;The default approach is simple and could be followed by official docs &lt;a href="https://the-guild.dev/graphql/codegen/docs/getting-started" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On high-level:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;install &lt;code&gt;@graphql-codegen/cli&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;pick a plugin for your stack: for example, &lt;a href="https://www.the-guild.dev/graphql/codegen/plugins/typescript/typescript-react-apollo" rel="noopener noreferrer"&gt;react-apollo&lt;/a&gt; and install it&lt;/li&gt;
&lt;li&gt;get your GraphQL Schema and Documents&lt;/li&gt;
&lt;li&gt;create basic &lt;code&gt;codegen.yml&lt;/code&gt; for &lt;code&gt;graphql-codegen&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;run &lt;code&gt;graphql-codegen&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In your &lt;code&gt;codegen.yml&lt;/code&gt;, you should specify schema, documents, where to save, and with what:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;schema.graphql&lt;/span&gt; &lt;span class="c1"&gt;# full schema; could be HTTP link&lt;/span&gt;
&lt;span class="na"&gt;documents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;documents.graphql&lt;/span&gt; &lt;span class="c1"&gt;# queries and mutations that you want to have&lt;/span&gt;
&lt;span class="na"&gt;generates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;./src/my-api/index.ts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# where to save&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;typescript&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;typescript-operations&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;typescript-react-apollo&lt;/span&gt; &lt;span class="c1"&gt;# stack that you are going to use&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ⚠️ CAUTION
&lt;/h2&gt;

&lt;p&gt;🌿 &lt;a href="https://docs.lens.xyz/docs/introduction:" rel="noopener noreferrer"&gt;https://docs.lens.xyz/docs/introduction:&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This API is beta and not production complete yet, which means that we could change schemas and endpoints at any time without warning or notice to you. When this API is production ready, we will remove this beta warning and will endeavor to ensure that there are no changes going forward unless a major change to the protocol itself is required.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Lens API is not production complete, and so is &lt;code&gt;@use-lens/*&lt;/code&gt;. Please, keep this in mind when going to production.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recommended use
&lt;/h3&gt;

&lt;p&gt;If you want to &lt;strong&gt;play with Lens API&lt;/strong&gt; - don't hesitate and install some of the &lt;code&gt;@use-lens/*&lt;/code&gt; packages - it will give you all you need to start.&lt;/p&gt;

&lt;p&gt;If you want to &lt;strong&gt;have more control&lt;/strong&gt; - use &lt;code&gt;@use-lens/cli&lt;/code&gt; to generate code locally. This would copy essential files that a package contains and would run &lt;code&gt;graphql-codegen&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You would be able to do more with &lt;code&gt;codegen.yml&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  👨‍🏫 React with Apollo Client
&lt;/h2&gt;

&lt;p&gt;For &lt;code&gt;@use-lens/react-apollo&lt;/code&gt;, I have prepared an example of how to use it.&lt;/p&gt;

&lt;p&gt;Check out the source code &lt;a href="https://github.com/use-lens/use-lens/tree/main/examples/react-apollo" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffhyf6utoa84gqjb66wzx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffhyf6utoa84gqjb66wzx.png" alt="use-lens-react-apollo-example.png" width="800" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F25d9qluy1e9dc99b4o47.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F25d9qluy1e9dc99b4o47.png" alt="use-lens-react-apollo-example-2.png" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🤝 Lens API Documents
&lt;/h2&gt;

&lt;p&gt;The complete set of Lens API Documents has been taken from &lt;a href="https://github.com/lens-protocol/api-examples" rel="noopener noreferrer"&gt;api-examples&lt;/a&gt;, a repo of Lens Protocol that shows how to use Lens API.&lt;br&gt;
The same (or similar) queries are given as examples in Lens API docs.&lt;/p&gt;

&lt;h2&gt;
  
  
  📚 Summary
&lt;/h2&gt;

&lt;p&gt;If you would like to use Lens API to see what it is - simplify your developer experience by using &lt;a href="https://github.com/use-lens/use-lens" rel="noopener noreferrer"&gt;@use-lens&lt;/a&gt; or &lt;a href="https://the-guild.dev/graphql/codegen" rel="noopener noreferrer"&gt;GraphQL Code Generator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks for reading! 🙇&lt;/p&gt;

</description>
      <category>web3</category>
      <category>graphql</category>
      <category>javascript</category>
      <category>lensprotocol</category>
    </item>
    <item>
      <title>Create Lens Subgraph on The Graph Protocol</title>
      <dc:creator>Andrii Shupta</dc:creator>
      <pubDate>Fri, 26 Aug 2022 10:21:20 +0000</pubDate>
      <link>https://dev.to/andriishupta/create-lens-subgraph-on-the-graph-protocol-32f0</link>
      <guid>https://dev.to/andriishupta/create-lens-subgraph-on-the-graph-protocol-32f0</guid>
      <description>&lt;h2&gt;
  
  
  🔗 Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/andriishupta/thegraph-hello-world" rel="noopener noreferrer"&gt;github: andriishupta/thegraph-hello-world&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://thegraph.com/hosted-service/subgraph/andriishupta/hello-world" rel="noopener noreferrer"&gt;subgraph: andriishupta/hello-world&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://thegraph.com/docs/en/developing/creating-a-subgraph/" rel="noopener noreferrer"&gt;TheGraph Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.lens.xyz/docs" rel="noopener noreferrer"&gt;Lens Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📰 Published on
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.andriishupta.dev" rel="noopener noreferrer"&gt;Personal blog 💻&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://andriishupta.medium.com" rel="noopener noreferrer"&gt;Medium ✍️&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ✨
&lt;/h2&gt;

&lt;p&gt;Initially, I got familiar with TheGraph by contributing to &lt;a href="https://twitter.com/developer_dao" rel="noopener noreferrer"&gt;DeveloperDAO&lt;/a&gt; to a project that did the same - indexing Lens Protocol.&lt;br&gt;
P.S. This tutorial is &lt;strong&gt;NOT&lt;/strong&gt; copy-paste of &lt;a href="https://github.com/Developer-DAO/Lens-Graph-Subgraph" rel="noopener noreferrer"&gt;existing code&lt;/a&gt;, and I created a repository from scratch to understand the basics of TheGraph and how to start. I needed to develop my subgraph to test how events would be indexed.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤓 Decentralized querying
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://thegraph.com/en/" rel="noopener noreferrer"&gt;The Graph&lt;/a&gt; is an indexing protocol for querying networks like Ethereum and IPFS. Anyone can build and publish open APIs, called subgraphs, making data easily accessible.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Many different tools and APIs help us query blockchain data using centralized API like we used to with web2. My favourites are &lt;a href="https://www.alchemy.com/" rel="noopener noreferrer"&gt;alchemy&lt;/a&gt; and &lt;a href="https://infura.io/" rel="noopener noreferrer"&gt;infura&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But, if we want to go decentralized, we must use decentralized tools.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;All data is stored and processed on open networks with verifiable integrity. TheGraph makes querying this data fast, reliable, and secure.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Lens
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://lens.xyz/" rel="noopener noreferrer"&gt;Lens Protocol&lt;/a&gt; is a composable and decentralized social graph, ready for you to build on so you can focus on creating a great experience, not scaling your users.&lt;/p&gt;

&lt;p&gt;Own your content.&lt;br&gt;
Own your social graph.&lt;br&gt;
Own your data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With &lt;a href="https://docs.lens.xyz/docs" rel="noopener noreferrer"&gt;Lens API&lt;/a&gt;, we could do everything we want with protocol, but it still includes the web2 principle and has a centralized database for different things built on top of Smart Contract data.&lt;/p&gt;

&lt;p&gt;If we want to get actual blockchain data, we need to use a protocol like TheGraph.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: assumption about the centralized part of Lens API is based on the features that Smart Contract has not, for example: "likes" functionality.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;I like Lens API very much and would count on it 99.9% of the time as a personal preference, balancing centralized vs. decentralized tooling&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  👀 How to create a subgraph
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;In this tutorial, I will give an example of creating a subgraph using &lt;a href="https://thegraph.com/hosted-service" rel="noopener noreferrer"&gt;Hosted Service&lt;/a&gt;&lt;/em&gt; - it will be closed in months. Still, there won't be a difference in coding approaches, just in how it is internally deployed. With the Hosted Service, it was easier to use for testing purposes.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://thegraph.com/docs/en/deploying/hosted-service/#create-a-subgraph" rel="noopener noreferrer"&gt;graph init&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;install &lt;a href="https://github.com/graphprotocol/graph-cli" rel="noopener noreferrer"&gt;graph-cli&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;run &lt;code&gt;graph init --product hosted-service&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;follow CLI steps where you need to add protocol, name, and contract address&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You will get a generated project. The main entry point is &lt;strong&gt;subgraph.yaml&lt;/strong&gt;.&lt;br&gt;
This is the finished version of my subgraph.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://github.com/andriishupta/thegraph-hello-world/blob/main/subgraph.yaml" rel="noopener noreferrer"&gt;source code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ewcsozcax6x41ombujy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4ewcsozcax6x41ombujy.png" alt="lens-subgraph-yaml.png" width="800" height="639"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You can read more on what is &lt;a href="https://thegraph.com/docs/en/developing/creating-a-subgraph/#the-subgraph-manifest" rel="noopener noreferrer"&gt;subgraph manifest&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  source block
&lt;/h4&gt;

&lt;p&gt;Indicates from what address to index. Many contracts use &lt;a href="https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies" rel="noopener noreferrer"&gt;Proxy Upgrade Pattern&lt;/a&gt;, which helps to fix crucial bugs or update implementation. That is why I have added LensHub ABI(&lt;a href="https://www.alchemy.com/overviews/what-is-an-abi-of-a-smart-contract-examples-and-usage" rel="noopener noreferrer"&gt;Application Binary Interface&lt;/a&gt;) as source ABI and then changed the address to &lt;a href="https://docs.lens.xyz/docs/deployed-contract-addresses" rel="noopener noreferrer"&gt;proxy&lt;/a&gt;&lt;br&gt;
&lt;code&gt;startBlock&lt;/code&gt; - I chose some random block for testing purposes, so it won't start indexing from the start - it takes more time. Usually, this value is omitted or equals the Contract creation's block.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8bzuc2owtopb934tznc5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8bzuc2owtopb934tznc5.png" alt="image.png" width="740" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To get ABI, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Copy from Etherscan/Polygonscan whole &lt;a href="https://polygonscan.com/address/0xDb46d1Dc155634FbC732f92E853b10B288AD5a1d#code" rel="noopener noreferrer"&gt;Contract ABI&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Go to &lt;a href="https://remix.ethereum.org/" rel="noopener noreferrer"&gt;remix.ethereum.org&lt;/a&gt;, copy the github project, and compile the contract&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I went with a 50/50 approach, such as Lens has &lt;a href="https://github.com/lens-protocol/lens-protocol/blob/main/contracts/libraries/Events.sol" rel="noopener noreferrer"&gt;&lt;code&gt;Events.sol&lt;/code&gt;&lt;/a&gt; library that is not compiled as part of the main contract.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;graph codegen&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;After proper setup, we can run code generation - we will get all types of code to work with.&lt;/p&gt;

&lt;p&gt;✨ &lt;a href="https://thegraph.com/docs/en/developing/creating-a-subgraph/" rel="noopener noreferrer"&gt;The Graph&lt;/a&gt; has excellent documentation, so follow it and find all answers there. ✨ &lt;/p&gt;

&lt;h3&gt;
  
  
  Mindset shift
&lt;/h3&gt;

&lt;p&gt;As a developer who worked with databases, I started to think linearly: entity created -&amp;gt; entity updated. But events could be indexed from &lt;code&gt;startBlock&lt;/code&gt; and in non-linear order in time, so even if we index the event like &lt;code&gt;handleProfileImageURISet&lt;/code&gt;, we need to check if the entity existed previously(more in the code example).&lt;/p&gt;

&lt;p&gt;To find more tips, TheGraph documentation has a section &lt;a href="https://thegraph.com/docs/en/developing/creating-a-subgraph/#defining-entities" rel="noopener noreferrer"&gt;"defining entities"&lt;/a&gt; - it entirely describes what you should think about when creating your schema.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Before defining entities, it is important to take a step back and think about how your data is structured and linked.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Code
&lt;/h3&gt;

&lt;p&gt;As we know - schema and how our data would be created is essential. Let's look at how I have added entity  definition:&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://github.com/andriishupta/thegraph-hello-world/blob/main/schema.graphql" rel="noopener noreferrer"&gt;source code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjbtriwiyvwmblykzxo7e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjbtriwiyvwmblykzxo7e.png" alt="lens-subgraph-schema.png" width="800" height="870"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Profile&lt;/code&gt; is the &lt;code&gt;@entity&lt;/code&gt;, including default fields that I took from &lt;a href="https://docs.lens.xyz/docs/events#profilecreated" rel="noopener noreferrer"&gt;&lt;code&gt;ProfileCreated&lt;/code&gt;&lt;/a&gt; event and the &lt;code&gt;posts&lt;/code&gt; field, which is an &lt;a href="https://thegraph.com/docs/en/developing/creating-a-subgraph/#entity-relationships" rel="noopener noreferrer"&gt;entity relationship&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this case, it is a "One-To-Many" relationship with the usage of the &lt;a href="https://thegraph.com/docs/en/developing/creating-a-subgraph/#reverse-lookups" rel="noopener noreferrer"&gt;Reverse Lookup&lt;/a&gt; approach that TheGraph recommends us using.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For one-to-many relationships, the relationship should always be stored on the 'one' side, and the 'many' side should always be derived. ... will result in dramatically better performance for both indexing and querying the subgraph...&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;Post&lt;/code&gt; is also an &lt;code&gt;@entity&lt;/code&gt;. Both have an &lt;code&gt;ID&lt;/code&gt;, which should be unique for the subgraph.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;lens-hub.ts&lt;/code&gt; are located functions that correspond to events we want to index.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;handle*Created&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;As we see, even for a new Post, we check if Profile already exists or not. I discovered the error I got during subgraph deployment and indexing that was saying something like "profile cannot be null" when I just wanted to load Profile to Post.&lt;/p&gt;

&lt;p&gt;TheGraph also supports the "merge" approach - this means that if we create a new instance of Profile and it already exists - it is okay cause the subgraph would try to merge fields. I wanted to be the more precise cause in the examples, and I saw that in every place where we wish to create something - we first check if it could be already created.&lt;/p&gt;

&lt;p&gt;Example: I have created a Post, and the subgraph knows that Post should have a Profile. Profile event was way before Post, so we don't have a Profile, and we need to create it; even if you could think - "how a Post could be created without a Profile" - it couldn't, but the event about the Post we could get first to index.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://github.com/andriishupta/thegraph-hello-world/blob/main/src/lens-hub.ts" rel="noopener noreferrer"&gt;source code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fok7qiw5ck5c55ls0i0tw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fok7qiw5ck5c55ls0i0tw.png" alt="lens-subgraph-profile-created.png" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy7w0m7yai4x8evqppila.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy7w0m7yai4x8evqppila.png" alt="lens-subgraph-post-created.png" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Testing
&lt;/h2&gt;

&lt;p&gt;To check out how it works, you could visit my &lt;a href="https://thegraph.com/hosted-service/subgraph/andriishupta/hello-world" rel="noopener noreferrer"&gt;subgraph: andriishupta/hello-world&lt;/a&gt;. It has a pre-defined "Test" query that will give you info for both Profiles and Posts. You could modify it to get more or less information in the query window.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fizju8fanu5r7qyi2oubv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fizju8fanu5r7qyi2oubv.png" alt="lens-subgraph-example.png" width="800" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🙇
&lt;/h2&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>thegraph</category>
      <category>lens</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>Generate Dummy Data in Strapi</title>
      <dc:creator>Andrii Shupta</dc:creator>
      <pubDate>Tue, 16 Aug 2022 11:27:00 +0000</pubDate>
      <link>https://dev.to/andriishupta/generate-dummy-data-in-strapi-3j1k</link>
      <guid>https://dev.to/andriishupta/generate-dummy-data-in-strapi-3j1k</guid>
      <description>&lt;h2&gt;
  
  
  🔗 Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;github: &lt;a href="https://github.com/andriishupta/strapi-generate-seed-data" rel="noopener noreferrer"&gt;andriishupta/strapi-generate-seed-data&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Strapi's video with a general idea of how to &lt;a href="https://strapi.io/video-library/generate-dummy-data-in-strapi" rel="noopener noreferrer"&gt;"Generate dummy data"&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📰 Also published on
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.andriishupta.dev" rel="noopener noreferrer"&gt;Personal Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://andriishupta.medium.com" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🤓 Motivation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://strapi.io/" rel="noopener noreferrer"&gt;Strapi&lt;/a&gt; is powerful open-source headless CMS that helps projects control code customization with extensibility and, at the same time, don't worry about implementing a full-blown Content Management System on their own.&lt;/p&gt;

&lt;p&gt;So, after you have set up your Strapi, you want to build Front-End on top of it. You hire front-end developers who are stuck: "Ye, I can query for data via REST and GraphQL, but what data should I see? Could I have an example?"&lt;/p&gt;

&lt;p&gt;😬&lt;/p&gt;

&lt;p&gt;To avoid this, we would generate example data upfront.&lt;/p&gt;

&lt;h2&gt;
  
  
  🌱 How to seed data?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  "Generate dummy data"
&lt;/h3&gt;

&lt;p&gt;There is the &lt;a href="https://strapi.io/video-library/generate-dummy-data-in-strapi" rel="noopener noreferrer"&gt;video&lt;/a&gt; in Strapi's Video-library that gave me a direction on how to do it.&lt;/p&gt;

&lt;p&gt;The idea is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use &lt;code&gt;bootstrap&lt;/code&gt; &lt;a href="https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/functions.html#bootstrap" rel="noopener noreferrer"&gt;function&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;use &lt;a href="https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/entity-service-api.html" rel="noopener noreferrer"&gt;Entity Service API&lt;/a&gt; for interactions&lt;/li&gt;
&lt;li&gt;generate dummy data with &lt;a href="https://fakerjs.dev/" rel="noopener noreferrer"&gt;@faker-js/faker&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tip
&lt;/h3&gt;

&lt;p&gt;Your case 💯 would be more complicated, so don't forget that you could take almost everything from Strapi's &lt;a href="https://github.com/strapi/strapi" rel="noopener noreferrer"&gt;source code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The flow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;find a place on Strapi Admin you want to copy&lt;/li&gt;
&lt;li&gt;check URL and Network(in developer's inspection) to understand what is called&lt;/li&gt;
&lt;li&gt;find code(start with &lt;em&gt;controller&lt;/em&gt;) that corresponds to that calls&lt;/li&gt;
&lt;li&gt;enjoy&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🧑‍💻 Code
&lt;/h2&gt;

&lt;p&gt;We have a simple Todo application(duh) with a Todo collection and a Todo List as a page(single type) that we want to send to the front-end. Also, our Todos has media functionality, so we upload some.&lt;/p&gt;

&lt;p&gt;In the bootstrap function, we check for the development environment and decide if we should run seeding or not. Seeding would automatically run on the very first application run(valid when a developer clones an existing repository) and could be re-run with &lt;code&gt;yarn seed&lt;/code&gt; to force seed, which clears old and creates new data - &lt;code&gt;FORCE_APP_BOOTSTRAP_ONLY&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;🔗&lt;a href="https://github.com/andriishupta/strapi-generate-seed-data/blob/main/src/index.ts#L19" rel="noopener noreferrer"&gt;source code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Febkmao5xc2hn3g1xn0wk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Febkmao5xc2hn3g1xn0wk.png" alt="image.png" width="800" height="564"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Collection Type
&lt;/h3&gt;

&lt;p&gt;To create a todo using Entity Service API, we need to call the &lt;code&gt;create&lt;/code&gt; method with data that matches our entity. In the current example and during seeding, I have used "bulk promises" to run requests in parallel cause they are not dependent on each other.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://github.com/andriishupta/strapi-generate-seed-data/blob/main/src/_seed/todo.ts#L24" rel="noopener noreferrer"&gt;source code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fozcen857yx2g9wckx6hy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fozcen857yx2g9wckx6hy.png" alt="image.png" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And using faker, we fill a todo like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fphyu8zr86tsrbxh10jzs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fphyu8zr86tsrbxh10jzs.png" alt="image.png" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Single Type
&lt;/h3&gt;

&lt;p&gt;Fulfilling the "Todo List page" is the same as Collection, but keep in mind that it could be only one entry all the time. Also, it contains a Todo relation, so we get five todos to fill it.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://github.com/andriishupta/strapi-generate-seed-data/blob/main/src/_seed/todo-list-page.ts#L14" rel="noopener noreferrer"&gt;source code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd67hhspyyc20ha2a68f7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd67hhspyyc20ha2a68f7.png" alt="image.png" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Media Upload
&lt;/h3&gt;

&lt;p&gt;To attach media on a todo, we first need to upload that media and then link its id to the entity. Code has been copied from &lt;a href="https://github.com/strapi/strapi/blob/master/packages/core/upload/server/controllers/admin-upload.js#L57" rel="noopener noreferrer"&gt;Strapi's source code&lt;/a&gt;, modified, and I just created a helper function.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://github.com/andriishupta/strapi-generate-seed-data/blob/main/src/_seed/helpers.ts#L52" rel="noopener noreferrer"&gt;source code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp0pbxvpoabaf9o4g7tjw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp0pbxvpoabaf9o4g7tjw.png" alt="image.png" width="800" height="651"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example in Todo:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0qbikssku7kkjg4u3ivg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0qbikssku7kkjg4u3ivg.png" alt="image.png" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Results
&lt;/h2&gt;

&lt;p&gt;After opening the Admin panel, you will see generated data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flsnkczabka84m0d43h6u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flsnkczabka84m0d43h6u.png" alt="image.png" width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fptbw7asl8s6mpprweewj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fptbw7asl8s6mpprweewj.png" alt="image.png" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ✨
&lt;/h2&gt;

&lt;p&gt;Initially, I implemented this for &lt;a href="https://twitter.com/developer_dao" rel="noopener noreferrer"&gt;Developer DAO&lt;/a&gt;'s website &lt;a href="https://developerdao.com/" rel="noopener noreferrer"&gt;developerdao.com&lt;/a&gt;. Original code is located &lt;a href="https://github.com/Developer-DAO/cms" rel="noopener noreferrer"&gt;here&lt;/a&gt;(archived and moved to monorepo).&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>node</category>
      <category>strapi</category>
    </item>
    <item>
      <title>Setup Supabase with Nest.js</title>
      <dc:creator>Andrii Shupta</dc:creator>
      <pubDate>Tue, 16 Aug 2022 05:35:50 +0000</pubDate>
      <link>https://dev.to/andriishupta/setup-supabase-with-nestjs-2kka</link>
      <guid>https://dev.to/andriishupta/setup-supabase-with-nestjs-2kka</guid>
      <description>&lt;h2&gt;
  
  
  ❗️⚠️ Disclaimer
&lt;/h2&gt;

&lt;p&gt;This article is created for Supabase &lt;strong&gt;v1&lt;/strong&gt; and seems not to work with &lt;strong&gt;v2&lt;/strong&gt; due to the depreciation of some &lt;strong&gt;auth&lt;/strong&gt; methods. I will create a new article for &lt;strong&gt;v2&lt;/strong&gt; and leave it here. If you have already found a solution — let me know in the comments! Thanks!&lt;/p&gt;

&lt;h2&gt;
  
  
  🤓 My expectations from You
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You know what the Supabase is&lt;/li&gt;
&lt;li&gt;You know the Nest.js framework&lt;/li&gt;
&lt;li&gt;You will google what is beyond this tutorial if needed&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🤔 My use case for using Supabase in Nest.js
&lt;/h2&gt;

&lt;p&gt;I needed a polling mechanism that runs every 1 second and does some action.&lt;br&gt;
As Auth and DB, I have chosen to use Supabase cause I have seen some tutorials and wanted to try it out.&lt;/p&gt;

&lt;p&gt;At first, I wanted to use Next.js and Functions to do those operations by Cron Jobs, but it happens to be that the minimal time frame for Cron Job by Github(as the most accessible Cron provider) is only every 5 minutes.&lt;/p&gt;

&lt;p&gt;So I switched to the idea of a server(full) app with Nest.js. (want to deploy on &lt;a href="https://www.heroku.com/" rel="noopener noreferrer"&gt;Heroku&lt;/a&gt;)&lt;/p&gt;
&lt;h2&gt;
  
  
  🧑‍💻 How to use Supabase and Nest.js
&lt;/h2&gt;

&lt;p&gt;There is one single example of how to use Supabase as Auth library for your Nest.js application, but:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it didn't seem straightforward (actual implementation) to me, and I didn't want to use an external package&lt;/li&gt;
&lt;li&gt;it doesn't work as I wanted - it didn't have Supabase Client exposed from within the lib&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;it is still a good entry if you have never used Passport and need an example - it helped me to understand what to do in my code, so thanks **hiro1107&lt;/em&gt;* :)&lt;/p&gt;

&lt;p&gt;📑 examples: &lt;a href="https://supabase.com/docs/guides/examples" rel="noopener noreferrer"&gt;https://supabase.com/docs/guides/examples&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🧑‍💻 Github: &lt;a href="https://github.com/hiro1107/nestjs-supabase-auth" rel="noopener noreferrer"&gt;https://github.com/hiro1107/nestjs-supabase-auth&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;So I have decided to implement my way for Auth and Client.&lt;/p&gt;
&lt;h3&gt;
  
  
  Could we use Supabase on the Node.js back-end?
&lt;/h3&gt;

&lt;p&gt;In general, like Firebase, Supabase is a client-side tool that works from the client-side by providing the "anon" user with Row Level Security Policies, but it doesn't force us to use Supabase only on the client-side.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;With some rules, we can freely leverage the power of Supabase in our Node.js Server.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  🍴 Supabase basic setup
&lt;/h2&gt;

&lt;p&gt;There are a few key points that I want to mention before the code.&lt;/p&gt;
&lt;h3&gt;
  
  
  RLS Policies
&lt;/h3&gt;

&lt;p&gt;Enable it when you create tables&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnuv265l8iwbifwm37h5s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnuv265l8iwbifwm37h5s.png" alt="Image description" width="800" height="452"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;I recommend creating two by default:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;"anon" is rejected by default for ALL actions&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftiri9ntimdx7t6pk8kuw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftiri9ntimdx7t6pk8kuw.png" alt="Image description" width="800" height="421"&gt;&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ALL actions are only could be done by auth.uid(), if your app is "user-oriented"&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbrfqiiz7hu313a9o899k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbrfqiiz7hu313a9o899k.png" alt="Image description" width="800" height="382"&gt;&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;user_id&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;To make your application work with previous policies, don't forget to create the &lt;code&gt;user_id&lt;/code&gt; column on each table that you use: it should be NOT null auto-generated &lt;code&gt;auth.uid()&lt;/code&gt; field, so in this way, Supabase will always append the correct user to a row.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn06ymyr8fygqq56amdxi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn06ymyr8fygqq56amdxi.png" alt="Image description" width="800" height="385"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;You can bypass RLS with Service Keys if needed, but be careful.&lt;/p&gt;
&lt;h2&gt;
  
  
  🐱 Nest.js application
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Installs
&lt;/h3&gt;

&lt;p&gt;To make this work, we need to add a few libs in addition to Supabase:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i passport passport-jwt @nestjs/passport @supabase/supabase-js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;passport - handles everything related to Auth, does it magic that we don't need to care about&lt;/p&gt;

&lt;p&gt;passport-jwt - has a ready-to-use Strategy for JWT Auth&lt;/p&gt;

&lt;p&gt;@nestjs/passport - Nest.js's module for Passport&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;em&gt;How JWT Auth works with Passport&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;How JWT Auth works go beyond this article, but there are plenty of explanations for using Passport and passport-jwt in Nest.js. You can start by checking Nest.js's &lt;a href="https://docs.nestjs.com/security/authentication" rel="noopener noreferrer"&gt;Authentication&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What we need to know for our case: Supabase is JWT-based authorization, which handles everything on its side. On our side, we need to have the correct &lt;code&gt;SUPABASE_JWT_SECRET&lt;/code&gt;, which is used to decode JWTs. (located in Settings -&amp;gt; API)&lt;/p&gt;

&lt;h3&gt;
  
  
  Supabase folder
&lt;/h3&gt;

&lt;p&gt;🔗 &lt;a href="https://github.com/andriishupta/nestjs-supabase-setup/tree/main/src/common/supabase" rel="noopener noreferrer"&gt;Link&lt;/a&gt; to folder&lt;/p&gt;

&lt;p&gt;This is the main code you could copy to your code base, and it will just work. The module is a regular Nest.js module. Other files deserve a deeper look.&lt;/p&gt;

&lt;h3&gt;
  
  
  Strategy
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Passport has a rich ecosystem of strategies that implement various authentication mechanisms. While simple in concept, the set of Passport strategies you can choose from is large and presents a lot of variety&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Such as Supabase is JWT, we will use a ready-to-use passport-jwt strategy that does all decoding and other things for us.&lt;/p&gt;

&lt;p&gt;In this code, we extend PassportStrategy with JWT Strategy and pass config in the &lt;code&gt;super&lt;/code&gt; call.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;strange "extend" &lt;code&gt;PassportStrategy(Strategy)&lt;/code&gt; is TypeScript Mixins&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://github.com/andriishupta/nestjs-supabase-setup/blob/main/src/common/supabase/supabase.strategy.ts" rel="noopener noreferrer"&gt;source-code&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgen7rhtlerdrsp0cin94.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgen7rhtlerdrsp0cin94.png" alt="supabase strategy" width="800" height="675"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Guard
&lt;/h3&gt;

&lt;p&gt;With this guard, I have protected the whole application by providing &lt;code&gt;APP_GUARD&lt;/code&gt; in app.module.ts - a global way of guarding. You could use &lt;code&gt;UseGuard&lt;/code&gt; for routes that need to be protected.&lt;/p&gt;

&lt;p&gt;Here we extend AuthGuard with the &lt;code&gt;jwt&lt;/code&gt; strategy(this is how passport-jwt named Strategy under the hood). Easy.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://github.com/andriishupta/nestjs-supabase-setup/blob/main/src/common/supabase/supabase.guard.ts" rel="noopener noreferrer"&gt;source-code&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faxkmzxfioqwdkck8hhwu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faxkmzxfioqwdkck8hhwu.png" alt="supabase guard" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Service: &lt;code&gt;Scope.REQUEST&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This service will &lt;code&gt;createClient&lt;/code&gt; for every request and &lt;code&gt;setAuth&lt;/code&gt;, so we will have the correct user during all following service calls. Code implemented in "Singleton" manner so we will get the same instance in different places during the same request.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://github.com/andriishupta/nestjs-supabase-setup/blob/main/src/common/supabase/supabase.ts" rel="noopener noreferrer"&gt;source-code&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftv5khj98j9k5st2wkcf5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftv5khj98j9k5st2wkcf5.png" alt="supabase-service" width="800" height="1013"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Here comes an interesting part that happens with different libraries that hold client-side states:&lt;/p&gt;

&lt;p&gt;If we use client-side libs that hold state per user, on server OR SSR apps like Next.js, we need to be careful with those, such as it could be that when we create an instance of a library, it could become available for everyone who calls server/SSR apps.&lt;/p&gt;

&lt;p&gt;That is why it is essential to use &lt;code&gt;@Injectable({ scope: Scope.REQUEST })&lt;/code&gt; so our Supabase &lt;code&gt;createClient&lt;/code&gt; will be created per request, and we will set auth correctly.&lt;/p&gt;

&lt;p&gt;Another example: &lt;a href="https://react-query-v3.tanstack.com/guides/ssr#using-hydration" rel="noopener noreferrer"&gt;Next.js &amp;amp; SSR with react-query&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnkddcmvqe0w85q1ok20x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnkddcmvqe0w85q1ok20x.png" alt="Image description" width="800" height="317"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: I haven't tested it for multiple users yet, but I am pretty sure about it.&lt;/em&gt;&lt;br&gt;
I haven't found other ways to pass Auth with one Client in docs by appending &lt;code&gt;access_token&lt;/code&gt; - only &lt;code&gt;setAuth&lt;/code&gt; to Client directly.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Possible solution&lt;/em&gt;: Supabase could tweak auth flow, where with a unique setup, we can pass users in each request. With the Passport, we have the user in &lt;code&gt;req.user&lt;/code&gt; and can still access the Authorization header for &lt;code&gt;access_token&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  📭 Testing with Postman
&lt;/h2&gt;

&lt;p&gt;After everything is finished - let's try to call our server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwy9tx9un12ge6mfa8sy7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwy9tx9un12ge6mfa8sy7.png" alt="Image description" width="800" height="541"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;As expected, we get a 401 code - this is &lt;em&gt;passport.js&lt;/em&gt; does it check for JWT in our &lt;strong&gt;SupabaseGuard&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's now get a valid &lt;code&gt;access_token&lt;/code&gt; and repeat the call:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fokrxs9c735mvnphynn3s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fokrxs9c735mvnphynn3s.png" alt="Image description" width="800" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;💪 💪 💪&lt;/p&gt;

&lt;p&gt;&lt;em&gt;access token available after you log in with a user. In my case, I have just sent "Magic Link" and got &lt;code&gt;acces_token&lt;/code&gt; from the URL&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftkxbh38wzpda28xy3fnh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftkxbh38wzpda28xy3fnh.png" alt="Image description" width="800" height="170"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  📋 Summary - TL;DR;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;install required dependencies&lt;/li&gt;
&lt;li&gt;copy &lt;strong&gt;supabase&lt;/strong&gt; folder to your project&lt;/li&gt;
&lt;li&gt;add 3 SUPABASE_* variables to .env&lt;/li&gt;
&lt;li&gt;import &lt;em&gt;supabase.module&lt;/em&gt;: in app.module / &lt;a class="mentioned-user" href="https://dev.to/global"&gt;@global&lt;/a&gt;() auth.module / etc.&lt;/li&gt;
&lt;li&gt;provide global &lt;code&gt;APP_GUARD&lt;/code&gt; or use it where you need it with &lt;code&gt;UseGuard&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;use &lt;em&gt;supabase.ts&lt;/em&gt; in other services by &lt;code&gt;this.supabase.getClient()&lt;/code&gt; for Supabase calls&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔗 Links
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Github: &lt;a href="https://github.com/andriishupta/nestjs-supabase-setup" rel="noopener noreferrer"&gt;https://github.com/andriishupta/nestjs-supabase-setup&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nest.js's &lt;a href="https://docs.nestjs.com/security/authentication" rel="noopener noreferrer"&gt;Authentication&lt;/a&gt;, including JWT with Passport.js&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How to use &lt;a href="https://docs.nestjs.com/guards" rel="noopener noreferrer"&gt;Guards&lt;/a&gt; in Nest.js&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Supabase's Auth &lt;a href="https://github.com/hiro1107/nestjs-supabase-auth" rel="noopener noreferrer"&gt;example app with Nest.js&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://supabase.com/docs/reference" rel="noopener noreferrer"&gt;Supabase's docs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Link to &lt;a href="https://blog.devgenius.io/setup-supabase-with-nest-js-85041b03ec3a" rel="noopener noreferrer"&gt;Medium's copy of the article&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>nestjs</category>
      <category>jwt</category>
    </item>
    <item>
      <title>Cross-Origin iframe communication with Window.postMessage</title>
      <dc:creator>Andrii Shupta</dc:creator>
      <pubDate>Tue, 16 Aug 2022 05:19:00 +0000</pubDate>
      <link>https://dev.to/andriishupta/cross-origin-iframe-communication-with-windowpostmessage-31pp</link>
      <guid>https://dev.to/andriishupta/cross-origin-iframe-communication-with-windowpostmessage-31pp</guid>
      <description>&lt;h2&gt;
  
  
  🤔 Why do we need cross-origin iframe communication?
&lt;/h2&gt;

&lt;p&gt;Imagine that you need to integrate with the "3rd party service" that would be used as part of your application.&lt;/p&gt;

&lt;p&gt;Both of your companies are just start-ups, and we don't have a complete variety of tools that will make our lives easier, so we choose &lt;code&gt;iframe&lt;/code&gt; as the first option. We &lt;em&gt;must&lt;/em&gt; integrate what we have now for the beta version. After that, we will refactor the code and will use edge technologies, as our manager promised(😉)&lt;/p&gt;

&lt;p&gt;Their app(as an example) could show private information, possibly, some real-time bank details / shipping / trading details, and only available after user authorization.&lt;/p&gt;

&lt;h3&gt;
  
  
  🤓 What could be a better solution?
&lt;/h3&gt;

&lt;p&gt;The best version of integration(IMHO) would be to get a react library with components, hooks, utils, etc., that will do everything for us. For example, check out &lt;a href="https://stripe.com/docs/stripe-js/react" rel="noopener noreferrer"&gt;React Stripe.js Components&lt;/a&gt;. Second best - take an Open API(example &lt;a href="https://stripe.com/docs/api" rel="noopener noreferrer"&gt;Stripe API&lt;/a&gt;) and implement our own components.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤨 What are we going to build?
&lt;/h2&gt;

&lt;h4&gt;
  
  
  💭 Idea summary
&lt;/h4&gt;

&lt;p&gt;As the Parent app, we want to login within the &lt;code&gt;iframe&lt;/code&gt; with some token, so the &lt;code&gt;iframe&lt;/code&gt; could show relative information. Every N mins(5 secs in this case), our token would expire, and the &lt;code&gt;iframe&lt;/code&gt; needs to request another. As a bonus, we can change a theme from &lt;em&gt;dark&lt;/em&gt; to &lt;em&gt;light&lt;/em&gt;, which could happen from both sides.&lt;/p&gt;




&lt;p&gt;Mostly I would list code that is only related to the &lt;code&gt;iframe&lt;/code&gt; and &lt;code&gt;Web API&lt;/code&gt; part and won't focus on things like an app creation or an explanation of &lt;a href="https://nextjs.org/docs/deployment#managed-nextjs-with-vercel" rel="noopener noreferrer"&gt;&lt;em&gt;"how to deploy to Vercel"&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Parent and the Child apps would be our actual implementation of what we need. For the front-end, we are going to use &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt; and &lt;a href="https://chakra-ui.com/" rel="noopener noreferrer"&gt;Chakra-UI&lt;/a&gt; for components. We would deploy apps on &lt;a href="https://vercel.com/" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt; and &lt;a href="https://www.netlify.com/" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt;(to be truly cross-origin).&lt;/p&gt;

&lt;p&gt;Also, I would use &lt;a href="https://nx.dev/" rel="noopener noreferrer"&gt;Nrwl Nx's workspaces&lt;/a&gt; to have monorepo, keeping run/build processes seamless.&lt;/p&gt;

&lt;h2&gt;
  
  
  👨‍💻 Code(skip to this if you don't want to read the Intro)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🤖 "The Communicator."
&lt;/h3&gt;

&lt;p&gt;🔗 &lt;a href="https://iframe-communicator.vercel.app" rel="noopener noreferrer"&gt;https://iframe-communicator.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔗 Github: &lt;a href="https://github.com/andriishupta/iframe-communicator" rel="noopener noreferrer"&gt;https://github.com/andriishupta/iframe-communicator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is a "special" app you could use for &lt;strong&gt;&lt;em&gt;real-world testing&lt;/em&gt;&lt;/strong&gt; to see how messaging works in your app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvv0ta4ag6ay2bg0xrmv3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvv0ta4ag6ay2bg0xrmv3.png" alt="iframe-communicator.png" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🧑 Parent code
&lt;/h3&gt;

&lt;p&gt;🔗 &lt;a href="https://cross-origin-iframe-communication-with-nextjs-parent-app.vercel.app/" rel="noopener noreferrer"&gt;link&lt;/a&gt; to the deployed app&lt;/p&gt;

&lt;p&gt;🔗 source code is available for copying &lt;a href="https://github.com/andriishupta/cross-origin-iframe-communication-with-nextjs/blob/main/packages/parent-app/pages/index.tsx" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As for the Parent app, we will surely have &lt;code&gt;iframe&lt;/code&gt; rendered on our side. Let's start from it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fboijveg8ftfif3d10nmn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fboijveg8ftfif3d10nmn.png" alt="iframe3.png" width="800" height="935"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;iframeRef&lt;/strong&gt; is our &lt;a href="https://reactjs.org/docs/hooks-reference.html#useref" rel="noopener noreferrer"&gt;React.js reference&lt;/a&gt; to the DOM element, so we can later use it&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;onLoad&lt;/em&gt; - this would send my initial token&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Next: how we send the message is &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage" rel="noopener noreferrer"&gt;Window.postMessage&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The window.postMessage() method safely enables cross-origin communication between Window objects; e.g., between a page and a pop-up that it spawned, or between a page and an iframe embedded within it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7auz1mn8vcmfjk9rdq9d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7auz1mn8vcmfjk9rdq9d.png" alt="post-message.png" width="800" height="683"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;postMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;iframeRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentWindow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;postMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CHILD_APP_URL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// OR use '*' to handle all origins&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;postMessage&lt;/code&gt; takes a &lt;code&gt;message: Message&lt;/code&gt; as the argument - it is our own message &lt;strong&gt;kind&lt;/strong&gt; that we selected and agreed with the Child app to pass through:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The data is serialized using the structured clone algorithm. This means you can pass a broad variety of data objects safely to the destination window without having to serialize them yourself.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;To send actual message we are using &lt;code&gt;iframeRef.current.contentWindow&lt;/code&gt; as our &lt;code&gt;targetWindow&lt;/code&gt;(from documentation) and the function's second parameter is &lt;code&gt;targetOrigin&lt;/code&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Specifies what the origin of targetWindow must be for the event to be dispatched, either as the literal string "*"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I know my &lt;code&gt;targetOrigin&lt;/code&gt;, so I am passing it and suggesting you not neglect &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#security_concerns" rel="noopener noreferrer"&gt;security risks&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Last but not least, we want to listen to messages from the Child!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F26r5ac4d89rqadmwmzmu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F26r5ac4d89rqadmwmzmu.png" alt="listener.png" width="800" height="885"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Security and filtering: we accept only our messages that we are sure in&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// skip other messages for security reasons and avoid extensions alerts in console
if (event.origin !== CHILD_APP_URL) {
  return;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's get the data from the &lt;em&gt;MessageEvent&lt;/em&gt; and do some checks and act by business logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (message?.type === 'token-expired-from-child') {
  ...
} else if (message?.type === 'theme-from-child') {
  ...
} else {
  //  in case of some random message
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;*&lt;em&gt;for more options this code could be improved with switch/case(who likes), ternary operator, or object literals.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Finish up by adding a listener and return a callback for removal, so when a component goes down, you navigate to another page, where you don't need to listen for an &lt;code&gt;iframe&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;window.addEventListener('message', handler);
return () =&amp;gt; window.removeEventListener('message', handler);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  👶 Child code
&lt;/h3&gt;

&lt;p&gt;🔗 &lt;a href="https://lustrous-donut-e3b29a.netlify.app" rel="noopener noreferrer"&gt;link&lt;/a&gt; to the deployed app&lt;/p&gt;

&lt;p&gt;🔗 source code is available for copying &lt;a href="https://github.com/andriishupta/cross-origin-iframe-communication-with-nextjs/blob/main/packages/child-app/pages/index.tsx" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The approach is the same for the Child app, with a twist of where to call &lt;em&gt;postMessage&lt;/em&gt; - &lt;code&gt;window.parent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm3wlmmok208hhlzacd0t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm3wlmmok208hhlzacd0t.png" alt="child-post-message.png" width="800" height="886"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;And listening to the messages differs in &lt;code&gt;type&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4kgkkxkm566mtv3z4zbr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4kgkkxkm566mtv3z4zbr.png" alt="child-listener.png" width="800" height="822"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 Links
&lt;/h2&gt;

&lt;p&gt;🎨 Parent app: &lt;a href="https://cross-origin-iframe-communication-with-nextjs-parent-app.vercel.app" rel="noopener noreferrer"&gt;https://cross-origin-iframe-communication-with-nextjs-parent-app.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;👨‍💻 Github: &lt;a href="https://github.com/andriishupta/cross-origin-iframe-communication-with-nextjs" rel="noopener noreferrer"&gt;https://github.com/andriishupta/cross-origin-iframe-communication-with-nextjs&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;🤖 "The Communicator": &lt;a href="https://iframe-communicator.vercel.app" rel="noopener noreferrer"&gt;https://iframe-communicator.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;👨‍💻 Github for "The Communicator": &lt;a href="https://github.com/andriishupta/cross-origin-iframe-communication-with-nextjs" rel="noopener noreferrer"&gt;https://github.com/andriishupta/cross-origin-iframe-communication-with-nextjs&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📝 Summary
&lt;/h2&gt;

&lt;p&gt;Cross-Origin iframe communication could come in quite handy in specific situations, and we totally could take advantage of two-way messaging to make that even more dynamic. Check for yourself by clicking the examples.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>cors</category>
      <category>react</category>
      <category>iframe</category>
    </item>
  </channel>
</rss>
