<?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: dAppling</title>
    <description>The latest articles on DEV Community by dAppling (@dappling).</description>
    <link>https://dev.to/dappling</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%2F1111069%2Ffff762d6-b76d-46e5-8d73-56c0693d6068.png</url>
      <title>DEV Community: dAppling</title>
      <link>https://dev.to/dappling</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dappling"/>
    <language>en</language>
    <item>
      <title>Poetry in Imagery • Meta Image Generation in Next.js</title>
      <dc:creator>dAppling</dc:creator>
      <pubDate>Tue, 22 Aug 2023 18:15:48 +0000</pubDate>
      <link>https://dev.to/dappling/poetry-in-imagery-meta-image-generation-in-nextjs-3b27</link>
      <guid>https://dev.to/dappling/poetry-in-imagery-meta-image-generation-in-nextjs-3b27</guid>
      <description>&lt;p&gt;When I stroll through the web without intention, every link, title, and image vies for my attention.  With a goal in mind, those same links, titles, and images seem to lack dimension. I struggle to find the information I seek; behind each possible link lacking context, I'm left blind.&lt;/p&gt;

&lt;p&gt;Meta tags of a website are a helpful guide. Used to share information about potential content behind a link, these small tags can hold enormous amounts of useful data. As long as they are used correctly, that is. I hope their use is expanded and can help and inspire creators to put more energy into their own site's images.&lt;/p&gt;

&lt;h2&gt;
  
  
  Essence of Representation
&lt;/h2&gt;

&lt;p&gt;Meta tags provide glimpses into the content without requiring users to visit the page itself. These tags can articulate essential details like the title, description, and intended size of the site. Open Graph tags (og), introduced by Facebook, define a way to share a summary of the content, location data, media information, and &lt;a href="https://ogp.me/"&gt;more&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The tag for an arbitrary image, &lt;code&gt;og:image&lt;/code&gt;, I think has the most potential. These images are not mere visual aids; they are the distilled essence of the web page they represent. A visual haiku. For our app &lt;a href="https://www.dappling.network"&gt;dAppling&lt;/a&gt;, I wanted to follow GitHub's lead with a desire to give the user as much information as possible. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a7XITPAB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.blog/wp-content/uploads/2021/06/framework-open-graph-images_fig-1-GitHub-twitter-card.png%3Fresize%3D2400%252C1260" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a7XITPAB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.blog/wp-content/uploads/2021/06/framework-open-graph-images_fig-1-GitHub-twitter-card.png%3Fresize%3D2400%252C1260" alt="GitHub beautiful meta card" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By way of example, GitHub's meta images. Explained more in their &lt;a href="https://github.blog/2021-06-22-framework-building-open-graph-images/"&gt;A framework for building Open Graph images&lt;/a&gt; article, the image succinctly and, in my opinion, beautifully explains what you will see before you see it. I love these images. From this little representation, I have been able to quickly gather information and confidently ignore or navigate into the site.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Alchemist's Wand
&lt;/h2&gt;

&lt;p&gt;Creating these visual haiku is a craft, a magical art. With tools like &lt;a href="https://vercel.com/blog/introducing-vercel-og-image-generation-fast-dynamic-social-card-images"&gt;@vercel/og&lt;/a&gt; and &lt;a href="https://github.com/vercel/next.js"&gt;Next.js&lt;/a&gt;, I started my journey.&lt;/p&gt;

&lt;p&gt;A flick of the wrist and a small creation appeared &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gZysGEsB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kir3l8943aa5o835l11j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gZysGEsB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kir3l8943aa5o835l11j.png" alt="green dappling meta image" width="800" height="420"&gt;&lt;/a&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UEeoy9aW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1bqu380m93paxheshm8r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UEeoy9aW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1bqu380m93paxheshm8r.png" alt="blue dappling meta image" width="800" height="420"&gt;&lt;/a&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oDrhAvSs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lss3cgvn50v0f8y7iglk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oDrhAvSs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lss3cgvn50v0f8y7iglk.png" alt="yellow dappling meta image" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each project, tied to a unique gradient, becomes recognizable at a glance. To look under the leaves, &lt;a href="https://gist.github.com/Namaskar-1F64F/c851789c4df7d528c6c08ec60a9c90f8"&gt;here's a gist of the generator&lt;/a&gt;. The examples above use different IDs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;top &lt;code&gt;https://www.dappling.network/api/og?id=blog&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;middle &lt;code&gt;https://www.dappling.network/api/og?id=dog&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;bottom &lt;code&gt;https://www.dappling.network/api/og?id=bog&lt;/code&gt;, &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another gesture of the wand; a motion with emotion. Two new cards materialize. You can see the pretty gradient for each of them is consistent (The ID for the following two are &lt;code&gt;meow&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TKFyvLdl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cwvnby82lqe1vka2phhc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TKFyvLdl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cwvnby82lqe1vka2phhc.png" alt="project card" width="800" height="419"&gt;&lt;/a&gt; Our beautiful project card contains a preview at a glance. The deployment card adds two more elements. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--p8fOb-q4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rnf6k7ey8u43a5jnd0ga.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--p8fOb-q4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rnf6k7ey8u43a5jnd0ga.png" alt="deployment card" width="800" height="419"&gt;&lt;/a&gt; You can see, without navigating to the site, if your deployment passed or failed. You can get the "verified" badge after someone signs the deployment, attesting its legitimacy. &lt;/p&gt;
&lt;h3&gt;
  
  
  The Poetry and the Pitfalls • Next.js
&lt;/h3&gt;

&lt;p&gt;Now we come to the unfortunate story. I would love to say these things all worked perfectly, but the real-time creation of these images posed performance challenges. The metaphysical had to meet the physical world of server responses and loading times. You see, when apps like telegram, slack, discord, and the like try to get these images, the data must be created on the fly. This causes a few problems like, how do we get the information for the page on load? &lt;/p&gt;

&lt;p&gt;This is solved by &lt;a href="https://nextjs.org/docs/pages/building-your-application/data-fetching/get-server-side-props"&gt;&lt;code&gt;getServerSideProps&lt;/code&gt;&lt;/a&gt;, but also causes the performance hit. In the new app router, the &lt;a href="https://nextjs.org/docs/app/api-reference/functions/generate-image-metadata"&gt;&lt;code&gt;generateImageMetadata&lt;/code&gt;&lt;/a&gt; function should work nicely. However, when browsing the site normally, one must wait for the metadata to load, even though they are not concerned with the meta image, after all, they're already on the site.&lt;/p&gt;

&lt;p&gt;We scaled back, yet the essence remains. The images still capture the spirit, albeit in a more simplistic form. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IXOagvYB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dyox4mpbcdj0c9g26f17.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IXOagvYB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dyox4mpbcdj0c9g26f17.png" alt="project boring dappling card" width="800" height="420"&gt;&lt;/a&gt; &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q3GTCIvm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pv2yc6jen9x8q3pvgvz8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q3GTCIvm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pv2yc6jen9x8q3pvgvz8.png" alt="deployment boring dappling card" width="800" height="420"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h3&gt;
  
  
  Learnings and Such
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Meta tags are first come first used. That means, if you have multiple meta tags on the page, it'll probably use the first one encountered. This confused me because instead of being able to define site-wide metadata, I had to use Next.js's &lt;a href="https://nextjs.org/docs/pages/api-reference/components/head"&gt;&lt;code&gt;&amp;lt;Head&amp;gt;&lt;/code&gt;&lt;/a&gt; element on every page.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Head&amp;gt;
    &amp;lt;meta ...&amp;gt;
    &amp;lt;meta ...&amp;gt;
&amp;lt;/Head&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Having an &lt;code&gt;svg&lt;/code&gt; as a meta image will silently fail and ruin your day. Make them &lt;code&gt;png&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Using metadata website checkers do not accurately reflect exactly what will happen on each individual social media platform. They all have their own way to display the images. 

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://en.rakko.tools/tools/9/"&gt;open graph debugger&lt;/a&gt; - see if the images work&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://chrome.google.com/webstore/detail/meta-debugger/jfpdemgdamgplelnlmaecbonkfgfgomp#:~:text=Meta%20Debugger&amp;amp;text=Debug%20the%20head%20section%20of,icons%20and%20many%20more%20things."&gt;meta debugger&lt;/a&gt; - view tags in chrome dev tools useful for duplicates&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Using local metadata debugging does not accurately reflect the first load of your page. There is a chance the meta tags change as hooks return data. Keep this in mind when using extensions like &lt;a href="https://chrome.google.com/webstore/detail/localhost-open-graph-debu/kckjjmiilgndeaohcljonedmledlnkij"&gt;localhost open graph debugger&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;twitter:&lt;/code&gt; tags are used by more than just twitter.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full list of image related tags used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;meta property="og:url" content={url} /&amp;gt;
&amp;lt;meta itemProp="url" content={url} /&amp;gt;
&amp;lt;meta itemProp="image" content={imageUrl} /&amp;gt;
&amp;lt;meta name="image" content={imageUrl} /&amp;gt;
&amp;lt;meta property="og:image" content={imageUrl} /&amp;gt;
&amp;lt;meta property="og:image:alt" content="dAppling" /&amp;gt;
&amp;lt;meta property="og:image:type" content="image/png" /&amp;gt;
&amp;lt;meta property="og:image:width" content="1200" /&amp;gt;
&amp;lt;meta property="og:image:height" content="630" /&amp;gt;
&amp;lt;meta property="twitter:image" content={imageUrl} /&amp;gt;
&amp;lt;meta property="twitter:image:src" content={imageUrl} /&amp;gt;
&amp;lt;meta property="twitter:card" content="summary_large_image" /&amp;gt;
&amp;lt;meta name="twitter:site" content="@dApplingNetwork" /&amp;gt;
&amp;lt;meta name="twitter:creator" content="@dApplingNetwork" /&amp;gt;
&amp;lt;meta property="twitter:url" content="https://www.dappling.network" /&amp;gt;
&amp;lt;meta property="twitter:title" content="..." /&amp;gt;
&amp;lt;meta property="twitter:description" content="..." /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If I were to start over, the process simply is:&lt;/li&gt;
&lt;li&gt;start ideating, sketching, and playing with &lt;a href="https://og-playground.vercel.app"&gt;the og playground&lt;/a&gt; until you have struck inspiration and want to start migrating to your actual code.&lt;/li&gt;
&lt;li&gt;create either a new Next.js project or add the og endpoint to your existing project.&lt;/li&gt;
&lt;li&gt;modify the meta tags of your site to include the dynamic url. e.g. &lt;code&gt;https://www.dappling.network/api/og?type=project&amp;amp;id=${projectId}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;test with the tools above&lt;/li&gt;
&lt;li&gt;cross your fingers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're interested in our exact implementation, the full code can be found in &lt;a href="https://gist.github.com/Namaskar-1F64F/f499c85c286eaae6b2e6a7854539c140"&gt;this gist&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Art of the Web
&lt;/h2&gt;

&lt;p&gt;Meta image generation is both a technical task and an art form. How one can translate the complex into the simple while maintaining beauty. Like a haiku captures a moment, a well-crafted meta image reminds that even in the technical world of web development, there's room for poetry, beauty, and a touch of the metaphysical. &lt;/p&gt;

&lt;p&gt;Thank you for your time. If you need help, please reach out to me &lt;a href="https://t.me/folded_hands"&gt;on telegram&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;🙏❤️🌱 What a great day to be alive!&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>learning</category>
      <category>art</category>
    </item>
    <item>
      <title>How dAppling uses Filebase</title>
      <dc:creator>dAppling</dc:creator>
      <pubDate>Tue, 11 Jul 2023 15:00:26 +0000</pubDate>
      <link>https://dev.to/dappling/how-dappling-uses-filebase-26m7</link>
      <guid>https://dev.to/dappling/how-dappling-uses-filebase-26m7</guid>
      <description>&lt;p&gt;At the core of dAppling, we both build code and host the completed app, ensuring a convenient experience for our users and one akin to centralized hosting for their users.&lt;/p&gt;

&lt;p&gt;We interact with Filebase in two ways: putting things into the bucket and taking things out of the bucket. &lt;/p&gt;

&lt;h2&gt;
  
  
  Into the Bucket
&lt;/h2&gt;

&lt;p&gt;In a way, we use 'storage' in the sense popularized by Amazon because Filebase supports s3 APIs to store content. When a build is complete, we generate build artifacts and upload them to Filebase via the API. Once this process completes, we receive a 'receipt' containing the content identifier (CID) or hash of the uploaded content. This CID is stored with the project for use later when content needs to be accessed.&lt;/p&gt;

&lt;p&gt;This process is outlined in the following diagram in which a Uniswap developer wants to use dAppling.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PjuoqkTN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/amptlikiaxawtx9qoaqo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PjuoqkTN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/amptlikiaxawtx9qoaqo.png" alt="Request diagram of a dappling code build - how do you build a decentralized app" width="800" height="703"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Out of the Bucket
&lt;/h2&gt;

&lt;p&gt;When it comes to content access, there are two main methods. Users can either directly access the content via the CID using their local IPFS node or a gateway, or they can use an auto-updating URL created by dAppling. This URL could be an auto-generated link such as &lt;code&gt;garden-daisy.dappling.network&lt;/code&gt;, or a custom domain configured by the user, like &lt;code&gt;ipfs.uniswap.org&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  An aside of configuring a custom domain
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EwxJd5Cm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c4gpb37i6p843pliyino.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EwxJd5Cm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c4gpb37i6p843pliyino.png" alt="custom domain request diagram using dappling" width="800" height="566"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the first case of accessing the CID directly, the content may or may not be downloaded via Filebase. This is because some other IPFS nodes may have cached the content. However, if the content does not exist, the "pinned" files will be ultimately retrieved at Filebase's nodes.&lt;/p&gt;

&lt;p&gt;In the second case, we use Filebase's gateway directly to retrieve the content.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dRZ4xR6D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kegbos6y42kf7s10yaih.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dRZ4xR6D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kegbos6y42kf7s10yaih.png" alt="request diagram of accessing Firebase content via dappling" width="800" height="604"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How could this be improved?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Replace the Record Handling
&lt;/h3&gt;

&lt;p&gt;Currently, we use a CDN in front of Filebase's gateway, which also functions as a CDN. This process appears to involve one extra step. But how else could we allow users to use a custom domain that maps to an updatable CID?&lt;/p&gt;

&lt;p&gt;I think it might look something like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Filebase handles DNS records somehow. I know it involves certificate provisioning, which is a bummer. It would be nice to request a domain &lt;code&gt;ipfs.uniswap.org&lt;/code&gt; and have it return the records for a user to update.&lt;/li&gt;
&lt;li&gt;Filebase allows updating the CID associated with the domain programmatically. So when the Uniswap code is updated, we can update the domain.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Subdomain gateways
&lt;/h3&gt;

&lt;p&gt;As I detailed in my article about &lt;a href="https://dev.to/namaskar-dappling/hosting-static-sites-on-ipfs-46f"&gt;IPFS and resource paths&lt;/a&gt;, it's crucial to stay as close to the user's development environment as possible. Therefore, we stay away from anything hosted at a "path". &lt;/p&gt;

&lt;p&gt;From &lt;a href="https://consensys.net/diligence/blog/2021/06/ipfs-gateway-security/"&gt;consensys IPFS security article&lt;/a&gt;,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;TL;DR: Path-based IPFS gateways have a critical flaw: They effectively disable one of the essential security features of modern browsers: the same-origin policy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We therefore prefer having the user bring their domain to host, like using &lt;code&gt;ipfs.uniswap.org&lt;/code&gt;, or our preview domain like &lt;code&gt;garden-daisy.dappling.network&lt;/code&gt;. Because of this, we have sites that will not work on path gateways such as &lt;code&gt;gateway.dappling.network/&amp;lt;CID hash&amp;gt;&lt;/code&gt;. We would prefer the gateway support the subdomain version a la &lt;code&gt;&amp;lt;CID hash&amp;gt;.gateway.dappling.network&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;It would be ideal if Filebase supported these subdomains as the access is much faster than any other gateway, but meanwhile we will direct our users towards a subdomain version like &lt;code&gt;&amp;lt;CID hash&amp;gt;.ipfs.cf-ipfs.com&lt;/code&gt; &lt;/p&gt;

</description>
      <category>decentralization</category>
      <category>filebase</category>
      <category>ipfs</category>
      <category>learning</category>
    </item>
    <item>
      <title>How to: IPNS on my Domain?</title>
      <dc:creator>dAppling</dc:creator>
      <pubDate>Tue, 11 Jul 2023 13:27:29 +0000</pubDate>
      <link>https://dev.to/dappling/how-to-ipns-on-my-domain-2ff8</link>
      <guid>https://dev.to/dappling/how-to-ipns-on-my-domain-2ff8</guid>
      <description>&lt;p&gt;First, &lt;strong&gt;why would you want this?&lt;/strong&gt; IPNS is another way to access content on the IPFS network. Since the link to the content is set on the DNS itself, the attack surface is slightly smaller, as the malicious user would need access at the DNS level to be successful. Also, as it's closer to traditional website access, while also showing the user direct IPFS accessing of the content is happening.&lt;/p&gt;

&lt;p&gt;There's more information about &lt;a href="[https://docs.ipfs.tech/concepts/ipns/"&gt;what's IPNS?&lt;/a&gt; as well as a great guide about how &lt;a href="https://docs.ipfs.tech/concepts/dnslink/#resolve-dnslink-name"&gt;resolving DNSLink&lt;/a&gt; works, but I'll go over the steps in a very high-level manner here.&lt;/p&gt;

&lt;p&gt;The next steps you can try yourself, and you should be able to see &lt;a href="https://github.com/Uniswap/interface/releases/tag/v4.250.0"&gt;Uniswap's Interface&lt;/a&gt; at the end.&lt;/p&gt;

&lt;p&gt;1️⃣ Get your CID for the site you want to share with users. It will look something like &lt;code&gt;bafybeibngzztaxprxg6w423plup5kihnizu4t4fdcsq73wgqcayvjrxoaq&lt;/code&gt;.     &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can use &lt;a href="https://dappling.network"&gt;dAppling&lt;/a&gt; to build your code into a CID.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2️⃣ Go to your DNS provider and add a record to your domain. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choose the domain you want the users to type in. Usually, the root domain makes sense.&lt;/li&gt;
&lt;li&gt;Add a text record with the subdomain of &lt;code&gt;_dnslink&lt;/code&gt; and the value set as &lt;code&gt;dnslink=/ipfs/&amp;lt;CID&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TXT _dnslink   dnslink=/ipfs/bafybeibngzztaxprxg6w423plup5kihnizu4t4fdcsq73wgqcayvjrxoaq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want a subdomain, e.g. ipfs.example.com, the subdomain used would be &lt;code&gt;_dnslink.ipfs&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;TXT _dnslink.ipfs dnslink=/ipfs/bafybeibngzztaxprxg6w423plup5kihnizu4t4fdcsq73wgqcayvjrxoaq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3️⃣ After set, you can direct users to the site via IPNS and a gateway. These would be accessible with a gateway, like Cloudflare, using their &lt;code&gt;ipns&lt;/code&gt; path using subdomains (recommended):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;a href="https://example-com.ipns.cf-ipfs.com/#/"&gt;https://example-com.ipns.cf-ipfs.com/#/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://ipfs-example-com.ipns.cf-ipfs.com/#/"&gt;https://ipfs-example-com.ipns.cf-ipfs.com/#/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;or using paths (not recommended):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;a href="https://cloudflare-ipfs.com/ipns/example.com"&gt;https://cloudflare-ipfs.com/ipns/example.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a href="https://cloudflare-ipfs.com/ipns/ipfs.example.com"&gt;https://cloudflare-ipfs.com/ipns/ipfs.example.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What are the downsides?&lt;/strong&gt; For one, the record will not be updated if you push changes to your code. This will need to be either automated (if the DNS supports it) or done manually.&lt;/p&gt;

&lt;p&gt;We do not currently try updating the IPNS record as we handle the CID resolution automatically when setting up a domain on dAppling, but we think IPNS is an interesting access point, and it's more accessible.&lt;/p&gt;

</description>
      <category>ipfs</category>
      <category>ipns</category>
      <category>learning</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Hosting Static Sites on IPFS</title>
      <dc:creator>dAppling</dc:creator>
      <pubDate>Fri, 30 Jun 2023 15:47:26 +0000</pubDate>
      <link>https://dev.to/dappling/hosting-static-sites-on-ipfs-46f</link>
      <guid>https://dev.to/dappling/hosting-static-sites-on-ipfs-46f</guid>
      <description>&lt;p&gt;Well, I’ll start that IPFS isn’t special. It’s cool, yeah, but the problems faced when deploying sites to IPFS, discounting the potential loading time, and pinning issues, appear in any hosting environment. The root cause lies in how the resources to produce the webpage are accessed. When accessing a site through IPFS, one can think of it as a simple folder in the sense of a folder on one’s computer. &lt;/p&gt;

&lt;h2&gt;
  
  
  Absolute Paths - /some/examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Local File System Example
&lt;/h3&gt;

&lt;p&gt;Say you want to view your poker hand calculator web app. This existed on the web before, but you being the pragmatic data-saver, downloaded a local copy to your computer. The site was open source, after all. It’d be wrong to *&lt;strong&gt;&lt;em&gt;not&lt;/em&gt;&lt;/strong&gt;* keep an extra copy. Now how do you view it? &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Search for the folder. It might be less successful on Windows. 
a. Realize you don’t remember the name and manually traverse your download folder. You know it’s in there somewhere.
b. Ahh, there it is.&lt;/li&gt;
&lt;li&gt;Open up the index.html page. Notice in the supposed “web” browser, the file appears as a weird-looking URL, or is it a URI…&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6iah-om7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j6f0r1tbimfb13bn12v2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6iah-om7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j6f0r1tbimfb13bn12v2.png" alt="local path example in a white box" width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And observe the page is… blank?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lrlpwkOG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3vyq5w3gpxg0ayr1fg8y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lrlpwkOG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3vyq5w3gpxg0ayr1fg8y.png" alt="empty webpage with browser bar" width="800" height="810"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, yes, but that isn’t to say your file system didn’t try. You can see the requests made, and it’s a sea of red.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IT5XKyHf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7jvcuszjk0b7t7k1q6qm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IT5XKyHf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7jvcuszjk0b7t7k1q6qm.png" alt="chrome dev tools with errors" width="800" height="527"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why? Well, let’s look closer at a request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8K6_cTNe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r7hb1mwsawdgy94n4lnl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8K6_cTNe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r7hb1mwsawdgy94n4lnl.png" alt="an example request in chrome dev tools" width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The requested URL looks surprisingly even stranger.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Request URL: file:///_next/static/css/d22f27d70fc00611.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So where did all of the rest of the URL go? Clearly, in the top bar, you can see&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;file:///Users/shire/downloads/cool-websites/poker-calc/index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The answer lies in how relative and absolute URLs request resources. See, inside the index.html file, our CSS file is requested with a beginning &lt;code&gt;/&lt;/code&gt;.  This instructs the browser to request a resource with an implicit domain name. &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Common_questions/Web_mechanics/What_is_a_URL#absolute_urls_vs._relative_urls"&gt;Read more on MDN&lt;/a&gt;. So great, the &lt;code&gt;CSS&lt;/code&gt; file is being requested with an implicit domain name.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt;
      &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"preload"&lt;/span&gt;
      &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/_next/static/css/d22f27d70fc00611.css"&lt;/span&gt;
      &lt;span class="na"&gt;as=&lt;/span&gt;&lt;span class="s"&gt;"style"&lt;/span&gt;
    &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because there’s no domain name, the browser assumes the resource is at the root of my computer’s hard drive. You fool!&lt;/p&gt;

&lt;h3&gt;
  
  
  This does not work! Failure.
&lt;/h3&gt;

&lt;h2&gt;
  
  
  Domain Hosted Example
&lt;/h2&gt;

&lt;p&gt;So assume our poker app also exists at &lt;a href="https://pokercalc.app"&gt;https://pokercalc.app&lt;/a&gt;. When we visit the site, we implicitly request the &lt;code&gt;index.html&lt;/code&gt;. That is returned, and, what? Everything looks good. The requests are going through. You look through the network requests again, and they look, normal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;Request URL: https://pokercalc.app/_next/static/css/d22f27d70fc00611.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahh well, here’s where the implicit domain comes in with absolute URLs. The &lt;code&gt;[pokercalc.app](http://pokercalc.app)&lt;/code&gt; has been implicitly added to the request and since the resource is also on the web server, the file is returned.&lt;/p&gt;

&lt;h3&gt;
  
  
  This works! Success.
&lt;/h3&gt;

&lt;h2&gt;
  
  
  Sub-Path Hosted Example
&lt;/h2&gt;

&lt;p&gt;So what’s the big deal? Well, now assume the content, instead of being on &lt;code&gt;https://pokercalc.app&lt;/code&gt;, has a summer theme hosted on &lt;code&gt;https://pokercalc.app/summer&lt;/code&gt;. The same files will be requested, and the same requests again will be returned.&lt;/p&gt;

&lt;p&gt;Even though clearly our top bar shows the correct website&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;https://pokercalc.app/summer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The request seems to have chopped off the summer path.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;Request URL: https://pokercalc.app/_next/static/css/d22f27d70fc00611.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yet another victim of the implicit domain.&lt;/p&gt;

&lt;h3&gt;
  
  
  This does not work! Failure.
&lt;/h3&gt;

&lt;h2&gt;
  
  
  Relative Paths - More/examples
&lt;/h2&gt;

&lt;p&gt;To save the day, we have relative paths. Again, &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Common_questions/Web_mechanics/What_is_a_URL#absolute_urls_vs._relative_urls"&gt;more information on MDN&lt;/a&gt;. Walking through the same examples again, say we changed the HTML thusly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;&amp;lt;html&amp;gt;
&lt;/span&gt;  &amp;lt;head lang="en"&amp;gt;
    &amp;lt;meta charset="utf-8" /&amp;gt;
    &amp;lt;link
      rel="preload"
&lt;span class="gd"&gt;-     href="/_next/static/css/d22f27d70fc00611.css"
&lt;/span&gt;&lt;span class="gi"&gt;+     href="_next/static/css/d22f27d70fc00611.css"
&lt;/span&gt;      as="style"
    /&amp;gt;
    &amp;lt;/head&amp;gt;
&lt;span class="gd"&gt;&amp;lt;/html&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Local File System
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;file:///Users/shire/downloads/cool-websites/poker-calc/_next/static/css/d22f27d70fc00611.css&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Domain
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;https://pokercalc.app/_next/static/css/d22f27d70fc00611.css&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Path
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;https://pokercalc.app/summer/_next/static/css/d22f27d70fc00611.css&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And all of those requests are actually successful. Hooray!&lt;/p&gt;

&lt;h3&gt;
  
  
  These all work! Success.
&lt;/h3&gt;

&lt;h2&gt;
  
  
  IPFS
&lt;/h2&gt;

&lt;p&gt;Remember how I said IPFS isn’t much different than a simple folder? Well, it’s a bit more complicated than that. See sites accessed on IPFS can be accessed via their Content Identifier (&lt;a href="https://docs.ipfs.tech/concepts/content-addressing/"&gt;CID&lt;/a&gt;) in different ways. &lt;/p&gt;

&lt;p&gt;Native protocol: &lt;code&gt;ipfs://&amp;lt;CID&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Web gateway: &lt;code&gt;https://ipfs.io/ipfs/&amp;lt;CID&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;IPNS (web gateway): &lt;code&gt;https://ipfs.io/ipns/&amp;lt;domain name&amp;gt;&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;Behind our CDN: &lt;code&gt;https://preview-domain.dappling.network&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And while all of these would appear to work with relative URLs, there is a catch.&lt;/p&gt;

&lt;h2&gt;
  
  
  The catch…
&lt;/h2&gt;

&lt;p&gt;So we can’t just throw all of the URLs to relative and call it a day. Well, you can actually get close, and we did just that with a script aptly called &lt;code&gt;replacePaths&lt;/code&gt;.  Here are the replacements being made in the source code of the websites, and the full code can be found at this &lt;a href="https://gist.github.com/Namaskar-1F64F/6515b349e596bd712e4593a4d9a345c9"&gt;gist&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;replaceRules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="c1"&gt;// Replace all absolute paths with relative paths&lt;/span&gt;
  &lt;span class="c1"&gt;// Replace src="/example" with src="example" and href="/example" with href="example"&lt;/span&gt;
  &lt;span class="c1"&gt;// Replace url("/example") with url("example")&lt;/span&gt;
  &lt;span class="c1"&gt;// Replace src="/example" with src="example"&lt;/span&gt;
  &lt;span class="c1"&gt;// Replace href=\"\/example\" with href=\"example\"&lt;/span&gt;
  &lt;span class="c1"&gt;// Replace href: \"\/example\" with href: \"example\"&lt;/span&gt;
  &lt;span class="c1"&gt;// Replace href: "/example" with href: "example" and path: "/example" with path: "example"&lt;/span&gt;
  &lt;span class="c1"&gt;// Replace all /_next with _next&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How could this possibly fail? Well, besides modifying the source files with some basic string replacements and hoping for the best, there exists some nuance in NextJs and React routing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Routing in React
&lt;/h3&gt;

&lt;p&gt;I specifically looked into the NextJs router for this, but the React router should behave similarly. For every link on the page that is clickable, there is a destination. These again are going to be relative or absolute URLs and note that fully qualified domains like &lt;code&gt;https://example.com&lt;/code&gt; are also considered absolute URLs. There are also local browser states that are handled with functions like &lt;code&gt;Router.push&lt;/code&gt; which change the page content AND modify the URL in the top bar. Lucky for us, these are somewhat easy to think about as they follow the same patterns of relative and absolute URLs. &lt;/p&gt;

&lt;p&gt;For example, if we are on the page &lt;code&gt;[pokercalc.app/texas-holdem](http://pokercalc.app/texas-holdem)&lt;/code&gt; and we have a button that will &lt;code&gt;push&lt;/code&gt; the state to &lt;code&gt;/games&lt;/code&gt;, the browser will happily change the bar to &lt;code&gt;pokercalc.app/games&lt;/code&gt;. Good, right? &lt;/p&gt;

&lt;p&gt;Wrong!&lt;/p&gt;

&lt;p&gt;What if we were hosting this on a different path, say &lt;code&gt;pokercalc.app/summer/texas-holdem&lt;/code&gt;, and then tried pushing &lt;code&gt;/games&lt;/code&gt;? Well since the URL is clearly “absolute”, we get what we expect: &lt;code&gt;pokercalc.app/texas-holdem&lt;/code&gt;. No summer theme is to be found. The implicit domain strikes again.&lt;/p&gt;

&lt;p&gt;But what about &lt;code&gt;basePath&lt;/code&gt;?&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;basePath&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Good though, myself from a second ago. The NextJs config option &lt;a href="https://nextjs.org/docs/app/api-reference/next-config-js/basePath"&gt;basePath&lt;/a&gt; is made specifically for this. It’ll prepend all of the links with the specified &lt;code&gt;basePath&lt;/code&gt;. Hooray!&lt;/p&gt;

&lt;p&gt;but wait…&lt;/p&gt;

&lt;p&gt;Remember how we don’t know **&lt;strong&gt;&lt;em&gt;where&lt;/em&gt;&lt;/strong&gt;** our website will be accessed? How are we supposed to choose our &lt;code&gt;basePath&lt;/code&gt; at build time? Well, you simply cannot.&lt;/p&gt;

&lt;p&gt;There’s a GitHub repo with these things that I failed to find, but the basic idea is to change the code to make the site work wherever it is hosted.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;inject a &lt;code&gt;base&lt;/code&gt; into the document which will set the actual URL to a node on the document, accessible throughout the app.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scriptTxt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
(function () {
  const { pathname } = window.location
  const ipfsMatch = /.*\\b(Qm[1-9A-HJ-NP-Za-km-z]{44,}|b[A-Za-z2-7]{58,}|B[A-Z2-7]{58,}|z[1-9A-HJ-NP-Za-km-z]{48,}|F[0-9A-F]{50,})\\//.exec(pathname)
  const base = document.createElement('base')

  base.href = ipfsMatch ? ipfsMatch[0] : '/'
  document.head.append(base)
})();
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// .. &lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Head&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;script&lt;/span&gt; &lt;span class="na"&gt;dangerouslySetInnerHTML&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;__html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;scriptTxt&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Now I don’t know if this is simply a bad way to pass around a variable or if NextJs does something internal with it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Replace all links with a new component that actually uses the link:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BaseLink&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;LinkProps&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;BaseLinkProps&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;BaseLink&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;newAs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setNewAs&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newAs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;baseURI_as&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;baseURI&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;baseURI_as&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="nx"&gt;setNewAs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;baseURI_as&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newAs&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;as&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;newAs&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Change how the Router pushes as well. There is a possible solution that admittedly I didn’t follow to fruition. I stopped because I think the internal routing table, I believe Next has a way to map these routes to the javascript to load, but altering that file does not seem to be the approach. This is what I tried anyway, but I think I’m misunderstanding how routing works.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;basePathPush&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;newAs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;newAs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;newAs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;newAs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;basePathPush newAs.startsWith document&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;newAs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newAs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;baseURI&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newAs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A Table?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Absolute Paths&lt;/th&gt;
&lt;th&gt;Relative Paths&lt;/th&gt;
&lt;th&gt;NextJs Routing&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ipfs://&lt;/td&gt;
&lt;td&gt;Maybe. Haven’t tested recently&lt;/td&gt;
&lt;td&gt;Works for assets&lt;/td&gt;
&lt;td&gt;Maybe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://ipfs.io/ipfs/"&gt;https://ipfs.io/ipfs/&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Definitely not&lt;/td&gt;
&lt;td&gt;Works for assets&lt;/td&gt;
&lt;td&gt;Works for some navigation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://ipfs.io/ipns/"&gt;https://ipfs.io/ipns/&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Definitely not&lt;/td&gt;
&lt;td&gt;Works for assets&lt;/td&gt;
&lt;td&gt;Works for some navigation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://preview-domain.dappling.network"&gt;https://preview-domain.dappling.network&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Definitely&lt;/td&gt;
&lt;td&gt;Definitely&lt;/td&gt;
&lt;td&gt;Definitely&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So, clearly, the CDN version works fine, but we should have already known that. We’re hosting a static website through a domain. Absolute paths work how they should, and relative paths work how they were designed. I say designed because when developers are developing there is an implicit assumption of this running from a domain. &lt;/p&gt;

&lt;h2&gt;
  
  
  Examples
&lt;/h2&gt;

&lt;p&gt;Just to round it out, here are some examples to show what I was telling up there.&lt;/p&gt;

&lt;h3&gt;
  
  
  The site doesn’t work
&lt;/h3&gt;

&lt;p&gt;There was &lt;code&gt;useEffect&lt;/code&gt; on the first load that would cause the app to start off in a bad state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FixedYield&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextPage&lt;/span&gt; &lt;span class="o"&gt;=&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;useEffect&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;Router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/smart-yield/pools/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://cloudflare-ipfs.com/ipfs/bafybeiab75ag4g7qgdhfkkx454y72ubkrgd7jadhk4ipnndkbtpa2cluoy/"&gt;https://cloudflare-ipfs.com/ipfs/bafybeiab75ag4g7qgdhfkkx454y72ubkrgd7jadhk4ipnndkbtpa2cluoy/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Absolute pathing
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://cloudflare-ipfs.com/ipfs/bafybeihje65wpty2ecibevbc7o3nwu7vnbhdn6xua5d5p4ni44fipn6ppe/"&gt;https://cloudflare-ipfs.com/ipfs/bafybeihje65wpty2ecibevbc7o3nwu7vnbhdn6xua5d5p4ni44fipn6ppe/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s an example that has absolute paths. 404s galore.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m3nrQvi5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tmwfdw0gm1imqg6tvx1g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m3nrQvi5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tmwfdw0gm1imqg6tvx1g.png" alt="chrome dev console errors" width="800" height="548"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Relative pathing
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://cloudflare-ipfs.com/ipfs/bafybeighrlepp5pdmdcxir3zpwl2cjmdb6jma5danb3ex7i76ornmn6mbu/"&gt;https://cloudflare-ipfs.com/ipfs/bafybeighrlepp5pdmdcxir3zpwl2cjmdb6jma5danb3ex7i76ornmn6mbu/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s an example that replaces absolute paths with relative ones. You’ll see the sub-nav works, but re-writes the URL. The top nav doesn’t work. Not sure why.&lt;/p&gt;

&lt;h3&gt;
  
  
  Changes
&lt;/h3&gt;

&lt;p&gt;Here is a full preview of my changes. Still doesn’t quite hit the mark but might be a good place to start. Might need access from me to see.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Namaskar-1F64F/barnbridge-v2-frontend/commit/9770763297375d0f6f37f569d9a5679b47a53b55"&gt;https://github.com/Namaskar-1F64F/barnbridge-v2-frontend/commit/9770763297375d0f6f37f569d9a5679b47a53b55&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What did we learn?
&lt;/h2&gt;

&lt;p&gt;I don’t know about you, but I learned IPFS can be thought of as a website accessed on a path on a domain. One needs to consider that the URL will not be known at build time and it seems like the best option right now is just simply shoving the whole situation into a familiar box. By using a domain and serving the IPFS content behind our CDN, we make the websites as the user expects.&lt;/p&gt;

</description>
      <category>ipfs</category>
      <category>tooling</category>
      <category>learning</category>
      <category>frontend</category>
    </item>
  </channel>
</rss>
