Skip to main content

Next.js AMP Support

Introduction

Accelerated Mobile Pages (AMP) is an open-source framework designed by Google to create web pages that load fast on mobile devices. Next.js, as a versatile React framework, provides built-in support for AMP, allowing developers to easily create AMP-compatible pages for improved performance on mobile devices.

In this tutorial, we'll explore how to implement AMP in your Next.js applications, understand the benefits and limitations of AMP, and learn best practices for creating AMP-compatible pages.

What is AMP?

AMP (Accelerated Mobile Pages) is an open-source HTML framework that provides a streamlined way to create web pages that load almost instantaneously on mobile devices. It achieves this by:

  • Restricting HTML/CSS/JavaScript usage to a subset of capabilities
  • Prioritizing resource loading
  • Leveraging AMP caching for better performance

Google and other platforms often prioritize AMP pages in search results and provide special UI features for them (like the lightning bolt ⚡ icon in search results).

Why Use AMP with Next.js?

Implementing AMP in your Next.js application offers several advantages:

  1. Faster page loads: AMP pages typically load 4x faster with 10x less data compared to standard pages
  2. Better mobile experience: Optimized for mobile viewports and interactions
  3. Improved SEO: Potential ranking boost in Google search results
  4. Higher engagement: Faster pages typically lead to better conversion rates
  5. Simplified analytics: Built-in AMP analytics capabilities

AMP Configuration in Next.js

Next.js offers two modes for AMP support:

  1. Hybrid AMP: Your page is served as both regular HTML and AMP HTML
  2. AMP-only: Your page is only served as AMP HTML

Let's explore how to implement both approaches.

Basic AMP Setup

To enable AMP for a page in Next.js, you need to export a configuration object specifying the AMP mode:

jsx
// pages/amp-page.js
export const config = {
amp: true // AMP-only mode
};

function AMPPage() {
return (
<div>
<h1>This is an AMP-only page</h1>
<p>Welcome to my AMP page!</p>
</div>
);
}

export default AMPPage;

When you visit /amp-page, it will be served as an AMP page with the appropriate AMP HTML structure.

Hybrid AMP Setup

For hybrid AMP mode, you set the config value to 'hybrid' instead:

jsx
// pages/hybrid-amp.js
export const config = {
amp: 'hybrid' // Hybrid AMP mode
};

function HybridAMPPage() {
return (
<div>
<h1>This is a hybrid AMP page</h1>
<p>It can be served as regular HTML or AMP HTML</p>
</div>
);
}

export default HybridAMPPage;

With this configuration, the page will be available in both formats:

  • Regular HTML: /hybrid-amp
  • AMP HTML: /hybrid-amp?amp=1

Detecting AMP Mode

In hybrid mode, you might want to render different components depending on whether the page is being served as AMP or not. You can use the useAmp hook from next/amp:

jsx
// pages/adaptive-page.js
import { useAmp } from 'next/amp';

export const config = {
amp: 'hybrid'
};

function AdaptivePage() {
const isAmp = useAmp();

return (
<div>
<h1>This page adapts to AMP</h1>
{isAmp ? (
<p>You are viewing the AMP version</p>
) : (
<p>You are viewing the regular HTML version</p>
)}
</div>
);
}

export default AdaptivePage;

Working with AMP Components

AMP restricts standard HTML elements and provides its own set of components. Next.js allows you to use these components in your AMP pages.

AMP Image Component

Instead of the regular <img> tag, AMP requires using <amp-img>:

jsx
// pages/amp-image-example.js
export const config = {
amp: true
};

function AMPImageExample() {
return (
<div>
<h1>AMP Image Example</h1>
<amp-img
alt="Mountains"
width="550"
height="368"
src="https://images.unsplash.com/photo-1506905925346-21bda4d32df4"
layout="responsive"
/>
</div>
);
}

export default AMPImageExample;

Note that amp-img requires explicit width, height, and layout attributes to avoid content shifting during page load.

AMP Components Requiring Scripts

Many AMP components require specific scripts to be included. Next.js helps with this through the Head component from next/head:

jsx
// pages/amp-carousel-example.js
import Head from 'next/head';

export const config = {
amp: true
};

function AMPCarouselExample() {
return (
<>
<Head>
<script async key="amp-carousel" custom-element="amp-carousel" src="https://cdn.ampproject.org/v0/amp-carousel-0.1.js" />
</Head>

<h1>AMP Carousel Example</h1>

<amp-carousel width="450" height="300" layout="responsive" type="slides">
<amp-img
src="https://images.unsplash.com/photo-1558979158-65a1eaa08691"
width="450"
height="300"
alt="Landscape 1"
/>
<amp-img
src="https://images.unsplash.com/photo-1505144808419-1957a94ca61e"
width="450"
height="300"
alt="Landscape 2"
/>
<amp-img
src="https://images.unsplash.com/photo-1520454974749-611b7248ffdb"
width="450"
height="300"
alt="Landscape 3"
/>
</amp-carousel>
</>
);
}

export default AMPCarouselExample;

Common AMP Components in Next.js

Here are some frequently used AMP components and how to implement them in Next.js:

AMP Analytics

jsx
// Example with AMP Analytics
import Head from 'next/head';

export const config = { amp: true };

function AnalyticsExample() {
return (
<>
<Head>
<script async custom-element="amp-analytics" src="https://cdn.ampproject.org/v0/amp-analytics-0.1.js" />
</Head>

<amp-analytics type="googleanalytics">
<script type="application/json" dangerouslySetInnerHTML={{
__html: JSON.stringify({
vars: {
account: 'UA-XXXXXXXX-Y'
},
triggers: {
trackPageview: {
on: 'visible',
request: 'pageview'
}
}
})
}} />
</amp-analytics>

<h1>Analytics Example</h1>
<p>This page includes AMP analytics</p>
</>
);
}

export default AnalyticsExample;

AMP Form

jsx
// Example with AMP Form
import Head from 'next/head';

export const config = { amp: true };

function FormExample() {
return (
<>
<Head>
<script async custom-element="amp-form" src="https://cdn.ampproject.org/v0/amp-form-0.1.js" />
</Head>

<h1>AMP Form Example</h1>

<form method="post" action-xhr="/api/submit-form" target="_top">
<fieldset>
<label>
<span>Name:</span>
<input type="text" name="name" required />
</label>
<label>
<span>Email:</span>
<input type="email" name="email" required />
</label>
<input type="submit" value="Subscribe" />
</fieldset>
<div submit-success>
<template type="amp-mustache">
Thank you for subscribing, {{name}}!
</template>
</div>
<div submit-error>
<template type="amp-mustache">
Error! {{error}}
</template>
</div>
</form>
</>
);
}

export default FormExample;

AMP Validation

When developing AMP pages, it's crucial to ensure they meet AMP's strict requirements. Next.js automatically validates your AMP pages during development and will show errors in the console if there are validation issues.

To manually validate an AMP page:

  1. Open your page with ?amp=1 for hybrid pages
  2. Add #development=1 to the URL
  3. Open the browser console to see AMP validation messages

For example: http://localhost:3000/hybrid-amp?amp=1#development=1

Real-World Example: News Article

Let's create a simple news article page using AMP:

jsx
// pages/news/[id].js
import Head from 'next/head';
import { useRouter } from 'next/router';

export const config = {
amp: true
};

// Mock data - in a real app, this would come from an API or CMS
const articles = {
'1': {
title: 'Next.js Introduces New Features',
image: 'https://images.unsplash.com/photo-1555066931-4365d14bab8c',
date: 'May 15, 2023',
content: 'Next.js has announced several new features in its latest release...'
},
'2': {
title: 'The Future of Web Development',
image: 'https://images.unsplash.com/photo-1498050108023-c5249f4df085',
date: 'June 2, 2023',
content: 'Web development continues to evolve at a rapid pace...'
}
};

function NewsArticle() {
const router = useRouter();
const { id } = router.query;
const article = articles[id];

// Handle case when article doesn't exist or page is still loading
if (!article) {
return <p>Loading...</p>;
}

return (
<>
<Head>
<title>{article.title} | News Site</title>
<link rel="canonical" href={`https://example.com/news/${id}`} />
<script async custom-element="amp-social-share" src="https://cdn.ampproject.org/v0/amp-social-share-0.1.js" />
</Head>

<header>
<h1>{article.title}</h1>
<p>Published on {article.date}</p>
</header>

<amp-img
alt={article.title}
src={article.image}
width="1200"
height="720"
layout="responsive"
/>

<article>
<p>{article.content}</p>
</article>

<div className="social-sharing">
<p>Share this article:</p>
<amp-social-share type="twitter" width="45" height="33"></amp-social-share>
<amp-social-share type="facebook" width="45" height="33" data-param-app_id="123456789"></amp-social-share>
<amp-social-share type="linkedin" width="45" height="33"></amp-social-share>
</div>

<style jsx>{`
header {
margin-bottom: 20px;
}
h1 {
color: #333;
font-size: 2rem;
}
article {
line-height: 1.6;
font-size: 18px;
margin: 20px 0;
}
.social-sharing {
margin-top: 30px;
display: flex;
align-items: center;
}
.social-sharing p {
margin-right: 15px;
}
`}</style>
</>
);
}

export default NewsArticle;

To view this page, navigate to /news/1 or /news/2.

AMP Limitations and Considerations

When working with AMP in Next.js, keep these limitations in mind:

  1. JavaScript restrictions: Custom JavaScript is not allowed in AMP pages
  2. Limited CSS: Only inline CSS with a maximum size of 75KB is allowed
  3. Component restrictions: Some HTML elements are prohibited and must be replaced with AMP equivalents
  4. External resources: Limited to AMP-approved components and extensions
  5. Form handling: Forms require special handling with AMP-specific attributes

Best Practices for AMP in Next.js

  1. Start with AMP-first: Design your pages with AMP constraints in mind from the beginning
  2. Use hybrid AMP when needed: If you need features not available in AMP, use hybrid mode
  3. Optimize images: Always specify width, height, and appropriate layout for amp-img
  4. Test on real devices: AMP is mobile-focused, so test performance on actual mobile devices
  5. Validate regularly: Use the AMP validator during development to catch issues early
  6. Implement analytics: Use amp-analytics to track user interactions
  7. Include structured data: Add schema.org markup for rich search results

Summary

Next.js offers excellent support for AMP, making it easy to create fast-loading, mobile-optimized pages. By configuring pages for AMP-only or hybrid mode, you can leverage the performance benefits of AMP while maintaining the developer experience of Next.js.

In this guide, we've covered:

  • Basic AMP configuration in Next.js
  • Creating AMP-only and hybrid AMP pages
  • Working with AMP components
  • Validating AMP pages
  • Building a real-world AMP example
  • Understanding AMP limitations and best practices

AMP can significantly improve the loading speed and user experience for content-focused pages, particularly on mobile devices. By following the guidelines in this tutorial, you can create high-performance pages that meet AMP's requirements while leveraging Next.js's powerful features.

Additional Resources

Exercises

  1. Create an AMP-only blog post page with a responsive layout, images, and social sharing buttons.
  2. Build a hybrid AMP product page that shows additional interactive features in the non-AMP version.
  3. Implement AMP analytics to track page views and user interactions.
  4. Create an AMP form that submits data to a Next.js API route and shows success/error messages.
  5. Convert an existing complex Next.js page to AMP, addressing any validation issues that arise.


If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)