Tutorial

The 'opts' object

The AMP library accepts customizations via the "opts" javascript object.

AMP story pages

The opts object for rendering AMP story pages has the following structure:

const myOptsObj = {
  seo,
  templates: {
    text: ({ story, config, seo }) => <CustomTextTemplate story={story} config={config} seo={seo} />,
    video: ({ story, config, seo }) => <CustomVideoTemplate story={story} config={config} seo={seo} />
    // ... other templates
  },
  slots: {
    story: {
      "top-slot": ({ story, config }) => <MyTopSlot story={story} config={config} />,
      "bottom-slot": ({ story, config }) => <MyBottomSlot story={story} config={config} />
    }
  },
  render: {
    navbarRender: ({ config, theme }) => <CustomNavbar theme={theme} config={config} />,
    headerCardRender: ({ story, config }) => <CustHeaderCard story={story} config={config} />,
    footerRender: ({ story, config }) => <CustFooter story={story} config={config} />,
    infiniteScrollRender: ({ story, config, inlineConfig }) => <CustomInfiniteScroll story={story} config={config} firstFiveStoriesConfig={inlineConfig} />,
    authorCardRender:({story, config, theme}) => <CustomAuthorCard authors={story.authors} config={config} theme={theme} />,
    // ... other renders
    storyElementRender: {
      bigfactElementRender: ({ story, config, element }) => (
        <CustBigFact story={story} config={config} element={element} />
      )
      // ... other SE renders
    }
  },
// InfiniteScroll is powered by default with `amp-infinite-scroll` collection (there needs to be a collection created with slug `amp-infinite-scroll`. The stories from this collection power the infinite scroll)
 // if source is `custom` - we need to provide an async function for inlineConfig & remoteConfigEndpoint
 // if source is `relatedStoriesApi` - infiniteScroll is powered by relatedStoriesApi
  featureConfig: {
    infiniteScroll: {
      source: "custom",
      inlineConfig: async getCustomStoryList(){},
      remoteConfigEndpoint: "amp/api/infinite-scroll",
    }
  },
};
  • seo - this is the SEO object generated by quintype/seo
  • templates - pass your custom story templates here. If not passed, the default templates will be used
  • slots - config for story page slots
  • renders - umbrella term used for the different render props used to customize the default templates.
    • storyElementRender
    • relatedStoriesRender
    • headerCardRender
    • footerRender
    • infiniteScrollRender
    • navbarRender
    • authorCardRender
  • featureConfig - used to provide config for amp lib features.

This section is useful if you want to use custom templates. Else, jump to slots

Passing custom templates

Go to Custom Story Templates


Slots

Slots are nothing but functions that should return a react component.

You might want to use slots to add ads, some scripts etc. The <Head /> component may be used to put code in the head. Using it, custom scripts, css can be added. It uses react-helmet

ampRoutes(app, {
   slots: {
     story: {
       "top-slot": ({story, config}) => <MyTopSlot story={story} config={config} />
       "bottom-slot": ({story, config}) => <MyBottomSlot story={story} config={config} />
       "live-blog-card-slot": ({story, config, index, card}) => <MyLiveBlogCardSlot />
       "default-story-card-slot": ({story, config, index, card}) => <MyStoryCardSlot />
       "default-story-element-slot": ({story, config, cardIdx, storyElementIdx, storyElement}) => <MyStoryElementSlot/>
     }
   }
})

Here, story and config is same as what's mentioned above.

Slot Name Slot Type props description
top-slot story obj - {story, config}
bottom-slot story obj - {story, config}
live-blog-card-slot story obj - {story, config, index, card} card - the card above this slot. index - the 1st card has 0th index and so on
default-story-card-slot story obj - {story, config, index, card} This slot is placed after every card on non-liveblog story templates
default-story-element-slot story obj - {story, config, cardIdx, storyElementIdx, storyElement} This slot is placed after every story element on a non-liveblog story
related-story-card-slot story obj - {story, config, index, relatedStory} This slot is placed after every related story card (also read)

Feature Config

Feature config is an object that can be used to configure different features of amp lib.

  1. enableAds: used to enable/disable ads on different templates. top, body and bottom corresponds to top-ad, body-ad and bottom-ad respoectively. By default, the ads are shown if no featureConfig is given.
  2. relatedStories (also read)
    • storiesToTake: sets the number of related stories displayed. Defaults to 5
  3. infiniteScroll:
    • storySeparatorText: String that will be displayed by the separator that separates two infinite scroll stories. If nothing is passed, SCROLL FOR NEXT is displayed
  4. sidebarMenu
    • Optional. To tell amplib from where to pick items for the sidebar (Hamburger) menu, pass the slug of that menu group to opts.featureConfig.sidebarMenu.menuGroupSlug
    • This can be extended to subdomains as well. For example if you have a subdomain called world-news, set opts.domains["world-news"].featureConfig.sidebarMenu.menuGroupSlug. Now the sidebar menu on the subdomain world-news will pick items from whatever menu group you've set
    • go to hamburger-menu for more info
  5. webengage
    • isEnabled: (Boolean) Enable / disable the default webengage component.
  6. localization - used to provide localization of the hardcoded keywords (eg: "By", "Also Read" etc) to respective locale.
const exampleFeatureConfig = {
  enableAds: {
    default: {
      top: true / false,
      body: true / false,
      bottom: true / false
    },
    liveBlog: {
      top: true / false,
      body: true / false,
      bottom: true / false
    }
  },
  liveBlog: {
    dataPollInterval: "10000",
    dataMaxItemsPerPage: "50"
  },
  relatedStories: {
    storiesToTake: number
  infiniteScroll: {
    storySeparatorText: string
  },
  sidebarMenu: {
    menuGroupSlug: string
  },
  webengage:{
    isEnabled: boolean;
  },
  localization: {
    useLocaleDateStampOnGenericStory: object | function;
    translations: object | function,
  },
};

Renders

If you wish to customize the default templates, you can do so using the various render prop overrides that the library provides. These too are functions that should return react components

For example,

ampRoutes(app, {
  render: {
    navbarRender: ({config, theme}) => <div>CUSTOM NAVBAR</div>
    headerCardRender: ({story, config}) => <div>CUSTOM HEADER CARD</div>
    footerRender: ({story, config}) => <div>CUSTOM FOOTER</div>
    authorCardRender: ({story, config, theme}) => <div>CUSTOM AUTHOR CARD</div>,

    storyElementRender: {
      textElementRender: ({ story, config, element }) => (
        <div>
          <span>My Custom Text Element</span>
          <div className="">{element.text}</div>
        </div>
      )
    }
  }
});

Here too, story and config is same as what's mentioned above.

Render prop name children props details
headerCardRender - obj - {story, config}
relatedStoriesRender - obj - {relatedStories, config, story} relatedStories gives stories in the related stories collection
infiniteScrollRender - obj - {story, config, inlineConfig} inlineConfig is one part of the JSON config given to to the infinite scroll component.
storyElementRender (object containing all story element renders) - - -
bigfactElementRender obj - {story, config, element} element is the story element, same as what's found in the story API
answerElementRender obj - {story, config, element} - same -
questionElementRender obj - {story, config, element} - same -
qAndAElementRender obj - {story, config, element} - same -
summaryElementRender obj - {story, config, element} - same -
textElementRender obj - {story, config, element} - same -
youtubeElementRender obj - {story, config, element} - same -
brightcoveElementRender obj - {story, config, element} - same -
vidibleElementRender obj - {story, config, element} - same -
twitterElementRender obj - {story, config, element} - same -
titleElementRender obj - {story, config, element} - same -
instagramElementRender obj - {story, config, element} - same -
imageGalleryElementRender obj - {story, config, element} - same -
imageElementRender obj - {story, config, element} - same -
facebookElementRender obj - {story, config, element} - same -
embedRender obj - {story, config, element} - same -
dailyMotionRender obj - {story, config, element} - same -
blockquoteRender obj - {story, config, element} - same -
blurbRender obj - {story, config, element} - same -
alsoReadRender obj - {story, config, element} - same -
tableElementRender obj - {story, config, element} - same -
unsupportedElementRender obj - {story, config, element} - same
liveBlogCardTimeStamp - obj - {story, config, card} card is the live blog card