Using amp-list to Add Random Related Article Suggestions to a Next.js Static Site

TL;DR

I wanted to add random related articles at the bottom of blog posts, which is a common blog feature, but I wasn't sure how to do it on a static site. One approach would be to call ServersideProps every time, but I got confused about how to combine that with getStaticsProps. I didn't want to do server-side rendering every time since it would make things slower...

So the approach I took was to first implement an API in Next.js, then use amp-list to fetch from it and render the results.

amp-list and amp-mustache

amp-list is an AMP extension component that dynamically fetches data from a JSON endpoint and renders it using amp-mustache templates.

Here's an example from the official documentation (amp-list, amp-mustache):

<amp-list width="auto"
  height="100"
  layout="fixed-height"
  src="/static/inline-examples/data/amp-list-urls.json">
  <template type="amp-mustache">
    <div class="url-entry">
      <a href="{{url}}">{{title}}</a>
    </div>
</template>
</amp-list>

Official Playground

The JSON being used:

{
  "items": [
    {
      "title": "AMP YouTube Channel",
      "url": "https://www.youtube.com/channel/UCXPBsjgKKG2HqsKBhWA4uQw"
    },
    {
      "title": "AMP.dev",
      "url": "https://amp.dev/"
    },
    {
      "title": "AMP Validator",
      "url": "https://validator.amp.dev/"
    },
    {
      "title": "AMP Playground",
      "url": "https://playground.amp.dev/"
    }
  ]
}

Basically, you specify the layout and endpoint within <amp-list>, and define how to render inside <template type="amp-mustache">.

With amp-mustache, you can use variables as follows:

  1. Simple variables

{{variableName}}

<!-- Using template tag. -->
<template type="amp-mustache">
  Hello {{world}}!
</template>
  1. Render if variable exists

{{#section}}{{/section}}

<!-- Using template tag. -->
<template type="amp-mustache">
    {{#world}}
        Hello {{world}}!
    {{/#world}}
</template>
  1. Render if variable does not exist

{{^section}}{{/section}}

<!-- Using template tag. -->
<template type="amp-mustache">
    {{^world}}
        No World!
    {{/#world}}
</template>

Templates in JSX

Within JSX, these templates can be used like this:

<template type="amp-mustache">Hello {"{{world}}"}!</template>;

Implementation Plan

Based on the above, I'll create an endpoint like /api/otherarticles that returns something like:

[
  {
    "title": "test post",
    "url": "/posts/test"
  }
]

Then the amp-list implementation would look like:

<amp-list
	width="auto"
	height="200"
	layout="fixed-height"
	src={`/api/otherarticles`}
	items="."
>
	{/* @ts-ignore */}
	<template type="amp-mustache">
		title={"{{title}}"}
		url={"{{url}}"}
	</template>
</amp-list>;

API Implementation

In Next.js, you can create API endpoints by placing ts or other files under pages/api/.

pages/api/otherarticles.js

export default function handler(req, res) {
    const articles = {
        title: "test post",
        url: "/posts/test"
    }

    res.status(200).json(articles)
}

In the actual implementation, I create a cache similar to Adding Search Functionality to My Next.js Blog and then retrieve a specified number of files from a random array referencing that cache. The implementation for this blog can be found on GitHub.

Create an issue on GitHub about this article

Read Next