What Challenges I Faced in Integrating Web Stories into a Next.js Blogging Website

Nitish Kumar Singh

Dec 24, 2023

Hello, developers! In this blog post, I will discuss the challenges I faced while integrating Web Stories into my blogging website, built using Next.js.

I use Next.js for my site, and the image below shows how I manage routing in Next.js for my website at the time of writing this post.

Web Stories

Web stories are short, immersive, and visually engaging narratives presented in a slideshow format. Combining images, videos, and text, they offer an amazing way to share information. Designed for quick information sharing, web stories provide a mobile-friendly, bite-sized storytelling experience, ideal for capturing attention and conveying information in a concise and engaging manner.

To build Web Stories, we need to follow the AMP project, designed for writing HTML code using components provided by this project and some conditions. If you are not familiar with Web Stories, you can explore more about it by visiting Web-Stories, Creating your first Web Story, and reading the AMP HTML Specification.

The following code shows an example of HTML code for a Web Story, "Joy of Pets."

<!DOCTYPE html>
<html ⚡>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"/>
    <noscript>
      <style amp-boilerplate>
        body {
          -webkit-animation: none;
          -moz-animation: none;
          -ms-animation: none;
          animation: none;
        }
      </style>
    </noscript>
    <title>Joy of Pets: My</title>
    <link rel="canonical" href="pets.html">

    <script async src="https://cdn.ampproject.org/v0.js"></script>
    <script async custom-element="amp-story" src="https://cdn.ampproject.org/v0/amp-story-1.0.js"></script>
    <script async custom-element="amp-video" src="https://cdn.ampproject.org/v0/amp-video-0.1.js"></script>

    <link href="https://fonts.googleapis.com/css?family=Oswald:200,300,400" rel="stylesheet"/>
    <style amp-custom>
      amp-story {
        font-family: "Oswald", sans-serif;
        color: #fff;
      }
      amp-story-page {
        background-color: #000;
      }
      h1 {
        font-weight: bold;
        font-size: 2.875em;
        font-weight: normal;
        line-height: 1.174;
      }
      p {
        font-weight: normal;
        font-size: 1.3em;
        line-height: 1.5em;
        color: #fff;
      }
      q {
        font-weight: 300;
        font-size: 1.1em;
      }
      amp-story-grid-layer.bottom {
        align-content: end;
      }
      amp-story-grid-layer.noedge {
        padding: 0px;
      }
      amp-story-grid-layer.center-text {
        align-content: center;
      }
      .wrapper {
        display: grid;
        grid-template-columns: 50% 50%;
        grid-template-rows: 50% 50%;
      }
      .banner-text {
        text-align: center;
        background-color: #000;
        line-height: 2em;
      }
    </style>
    <style amp-boilerplate>
        body {
          -webkit-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
          -moz-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
          -ms-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
          animation: -amp-start 8s steps(1, end) 0s 1 normal both;
        }
        @-webkit-keyframes -amp-start {
          from {
            visibility: hidden;
          }
          to {
            visibility: visible;
          }
        }
        @-moz-keyframes -amp-start {
          from {
            visibility: hidden;
          }
          to {
            visibility: visible;
          }
        }
        @-ms-keyframes -amp-start {
          from {
            visibility: hidden;
          }
          to {
            visibility: visible;
          }
        }
        @-o-keyframes -amp-start {
          from {
            visibility: hidden;
          }
          to {
            visibility: visible;
          }
        }
        @keyframes -amp-start {
          from {
            visibility: hidden;
          }
          to {
            visibility: visible;
          }
        }
    </style>
  </head>
  <body>
    <amp-story standalone title="Joy of Pets" publisher="AMP tutorials"
     publisher-logo-src="assets/AMP-Brand-White-Icon.svg" poster-portrait-src="assets/cover.jpg">
      <amp-story-page id="cover">
        <amp-story-grid-layer template="fill">
          <amp-img src="assets/cover.jpg" width="720" height="1280" layout="responsive" alt=""> </amp-img>
        </amp-story-grid-layer>
        <amp-story-grid-layer template="vertical">
          <h1>The Joy of Pets</h1>
          <p>By AMP Tutorials</p>
        </amp-story-grid-layer>
      </amp-story-page>
      <amp-story-page id="page1">
        <amp-story-grid-layer template="vertical">
          <h1>Cats</h1>
          <amp-img
            src="assets/cat.jpg"
            width="320"
            height="580"
            layout="responsive">
          </amp-img>
          <q>Dogs come when they're called. Cats take a message and get back toyou. --Mary Bly</q>
        </amp-story-grid-layer>
      </amp-story-page>
        <!-- Page 2 (Dog): 2 layers (fill + thirds) -->
        <amp-story-page id="page2">
        <amp-story-grid-layer template="fill">
            <amp-img
            src="assets/dog.jpg"
            width="720"
            height="1280"
            layout="responsive"
            >
            </amp-img>
        </amp-story-grid-layer>
        <amp-story-grid-layer template="thirds">
            <h1 grid-area="upper-third">Dogs</h1>
            <p grid-area="lower-third">
            Dogs were probably the first tame animals. They have accompanied
            humans for some 10,000 years. Some scientists assert that all dogs,
            domestic and wild, share a common ancestor in the small South Asian
            wolf.
            </p>
        </amp-story-grid-layer>
        </amp-story-page>

        <!-- Page 3 (Bird): 3 layers (fill + vertical + vertical) + Audio-->
        <amp-story-page id="page3" background-audio="assets/bird-singing.mp3">
        <amp-story-grid-layer template="fill">
            <amp-img
            src="assets/bird.jpg"
            width="720"
            height="1280"
            layout="responsive"
            >
            </amp-img>
        </amp-story-grid-layer>
        <amp-story-grid-layer template="vertical">
            <h1>Birds</h1>
        </amp-story-grid-layer>
        <amp-story-grid-layer template="vertical" class="bottom">
            <q animate-in="fly-in-left"
            >A bird is three things: Feathers, flight and song, And feathers are
            the least of these. -Marjorie Allen Seiffert</q
            >
        </amp-story-grid-layer>
        </amp-story-page>

        <!-- Page 4 (Rabbit): 3 layers (fill (video) + vertical + vertical) -->
        <amp-story-page id="page4">
        <amp-story-grid-layer template="fill">
            <amp-video
            autoplay
            loop
            width="720"
            height="1280"
            poster="assets/rabbit.jpg"
            layout="responsive"
            >
            <source src="assets/rabbit.mp4" type="video/mp4" />
            </amp-video>
        </amp-story-grid-layer>
        <amp-story-grid-layer template="vertical">
            <h1>Rabbits</h1>
        </amp-story-grid-layer>
        <amp-story-grid-layer template="vertical" class="bottom">
            <p>
            Rabbits can learn to follow simple voice commands and come when
            called by name, and are curious and playful.
            </p>
        </amp-story-grid-layer>
        </amp-story-page>

        <!-- Page 5 (Collage): 2 layers + animations -->
        <amp-story-page id="page5">
        <amp-story-grid-layer template="vertical" class="noedge">
            <div class="wrapper">
            <amp-img
                src="assets/cat.jpg"
                width="720"
                height="1280"
                layout="responsive"
                animate-in="fade-in"
                animate-in-delay="0.4s"
            >
            </amp-img>
            <amp-img
                src="assets/dog.jpg"
                width="720"
                height="1280"
                layout="responsive"
                animate-in="fade-in"
                animate-in-delay="0.6s"
            >
            </amp-img>
            <amp-img
                src="assets/bird.jpg"
                width="720"
                height="1280"
                layout="responsive"
                animate-in="fade-in"
                animate-in-delay=".8s"
            >
            </amp-img>
            <amp-img
                src="assets/rabbit.jpg"
                width="720"
                height="1280"
                layout="responsive"
                animate-in="fade-in"
                animate-in-delay="1s"
            >
            </amp-img>
            </div>
        </amp-story-grid-layer>
        <amp-story-grid-layer template="vertical" class="center-text">
            <p class="banner-text" animate-in="whoosh-in-right">
            Pets can lower your stress levels!
            </p>
        </amp-story-grid-layer>
        </amp-story-page>
    </amp-story>
  </body>
</html>

According to the AMP HTML Specification, I need to completely change HTML code to the above format, where we need to add or amp as an attribute in the HTML opening tag, keep only one amp-story tag as a child in the body tag, and add some scripts and styles in the head section.

The following image shows the folder structure of "Routing-Types" that I have tried for interacting with web stories.

I want to show a preview of all Web Stories using page.js of the web-stories folder when the URL path is "/web-stories" and show a Web Story using "page.js" of the "[story-path]" folder when the URL path is "web-stories/routing-in-next-js_story-id.

But the problem is that when the story page is routed, we need to change HTML to AMP HTML. For doing this, we need to conditionally render "RootLayout" for the traditional web page where the Navbar and more components do not change when navigating to different URLs and the AMP web page where we include only one "amp-story" tag that comes from the story page as children props.

I have tried both Next.js Parallel Routing and Routes Groups, but it did not work as I wanted. In Routes Groups, it works well but reloads the page every time when a new story is opened from the stories page because of Routes Group shifting.

I want to show the Story-Page without a page reload, whether the story opens directly or by navigating from the "Web-Stories-Page" with Server-Side rendering.

So, I'm going to take complete control of my blogging website using Express.js on the back-end side on Vercel and manage the front-end using pure JavaScript.

If anyone has ideas on how to build it using Next.js, please provide only some hints or suggestions on how to achieve this using Next.js because taking full control over the front-end and back-end is painful and requires writing a lot of code. Thanks in advance.

Published on Dec 24, 2023
Comments (undefined)

Read More