Full Stack Development

Search Engine Optimisation (SEO)



by Tomas Trescak t.trescak@westernsydney.edu.au

SEO

/

Introduction

  • Boosts discoverability
  • Next.js simplifies SEO
  • 👺 Myth : SEO = Keywords + Meta

SEO

/

Static Metadata

    import type { Metadata } from 'next'
 
export const metadata: Metadata = {
  title: '...',
  description: '...',
}
 
export default function Page() {}
  

SEO

/

Dynamic Metadata

    import { fetchPostBySlug, type Post } from '@/lib/api';

type Params = { slug: string } 

export async function generateMetadata({ params }: { params:  Params }) {
  const post: Post = await fetchPostBySlug(params.slug);
  return {
    title: `${post.title} | My Blog`,
    description: post.excerpt,
    alternates: { canonical: `https://myblog.com/posts/${params.slug}` },
    openGraph: {
      title: post.title,
      description: post.excerpt,
      images: [post.featuredImage],
    },
  };
}

export default async function PostPage({ params }: { params: Params }) {
  // ...
}
  

SEO

/

Dynamic Metadata

    export const dynamic = 'force-static';
export const revalidate = 31536000;

export async function generateMetadata({ params }: { params: Params }) {
  const post: { title: string; excerpt: string } = await fetchPostBySlug(params.slug);
  return {
    title: `${post.title} | My Blog`,
    description: post.excerpt,
    robots: { index: true, follow: true },
  };
}

export const headers = () => ({
  'Cache-Control': 'public, max-age=31536000, immutable',
  'X-Robots-Tag': 'index, follow',
});


export default async function PostPage({ params }: { params: Params }) {
  const post = await fetchPostBySlug(params.slug);
  // ...
}
  

SEO

/

Images and Structured Data

    import Image from 'next/image';
import { fetchPostBySlug, type Post } from '@/lib/api';

export async function generateMetadata({ params }: { params: Params }) {
  const post: Post = await fetchPostBySlug(params.slug);
  return { title: `${post.title} | My Blog`, description: post.excerpt };
}

export default async function PostPage({ params }: { params: Params }) {
  const post: Post = await fetchPostBySlug(params.slug);
  const schema = {
    '@context': 'https://schema.org',
    '@type': 'BlogPosting',
    headline: post.title,
    image: post.featuredImage,
    datePublished: post.date,
    author: { '@type': 'Person', name: post.author },
  };

  return (
    <div>
      <script type="application/ld+json" dangerouslySetInnerHTML={
        { __html: JSON.stringify(schema) }
      } />
      <h1>{post.title}</h1>
      <Image 
        src={post.featuredImage} 
        alt={post.title} 
        width={800} 
        height={400} 
        priority 
      />
      <p>{post.content}</p>
    </div>
  );
}
  

SEO

/

Wrap-Up

  • Use metadata export or generateMetadata
  • Set headers, robots wisely
  • Duplicate content or slow images hurt rankings
  • Generate sitemap.xml if there are no links from landing page
  • Follow best practices