SEO

SEO is crucial for enhancing your platform’s visibility on search engines like Google. This document outlines the key Search Engine Optimization (SEO) strategies implemented to boost your site's ranking and drive more organic traffic.

Features

🏷️ Meta Tags: Essential meta tags for better search engine visibility and social media sharing.

🛠️ JSON-LD Schema: Structured data to help search engines understand your content.

🌐 Sitemap: A dynamically generated sitemap for efficient web crawling.

🤖 robots.txt: A file to guide search engines on what to crawl and what to ignore.

🔗 Link Tags: Canonical URLs, icons, and other link-related optimizations.

Script Optimization: Optimizing scripts for performance and SEO-friendly integration.

🖼️ Image Optimization: Utilizing Next.js next/image to serve optimized images for faster loading times.

What's Included

Meta Tags

Meta tags provide key information to search engines and social media platforms. They include tags like title, description, keywords, and Open Graph tags for platforms like Facebook, and Twitter tags for Twitter sharing. You can define static metadata by adding the export const metadata argument inside page.tsx or layout.tsx:

import type { Metadata } from 'next';
 
export const metadata: Metadata = {
  metadataBase: new URL('https://startbase.dev'),
  openGraph: {
    siteName: 'Startbase',
    type: 'website',
    locale: 'en_US',
  },
  robots: {
    index: true,
    follow: true,
    'max-image-preview': 'large',
    'max-snippet': -1,
    'max-video-preview': -1,
    googleBot: 'index, follow',
  },
  alternates: {
    types: {
      'application/rss+xml': 'https://startbase.dev/rss.xml',
    },
  },
  applicationName: 'Startbase',
  appleWebApp: {
    title: 'Startbase',
    statusBarStyle: 'default',
    capable: true,
  },
  verification: {
    google: 'YOUR_DATA',
    yandex: ['YOUR_DATA'],
    other: {
      'msvalidate.01': ['YOUR_DATA'],
      'facebook-domain-verification': ['YOUR_DATA'],
    },
  },
  icons: {
    icon: [
      {
        url: '/favicon.ico',
        type: 'image/x-icon',
      },
      {
        url: '/favicon-16x16.png',
        sizes: '16x16',
        type: 'image/png',
      },
    ],
    shortcut: [
      {
        url: '/favicon.ico',
        type: 'image/x-icon',
      },
    ],
    apple: [
      {
        url: '/apple-icon-57x57.png',
        sizes: '57x57',
        type: 'image/png',
      },
      {
        url: '/apple-icon-60x60.png',
        sizes: '60x60',
        type: 'image/png',
      },
    ],
  },
};

For dynamic metadata you can use generateMetedata, generateMetadata should return a Metadata object containing one or more metadata fields. You can put this function into [slug]/page.tsx:

import type { Metadata, ResolvingMetadata } from 'next';
 
type Props = {
  params: { id: string };
  searchParams: { [key: string]: string | string[] | undefined };
};
 
export async function generateMetadata(
  { params, searchParams }: Props,
  parent: ResolvingMetadata
): Promise<Metadata> {
  const id = params.id;
 
  const product = await fetch(`https://.../${id}`).then((res) => res.json());
 
  const previousImages = (await parent).openGraph?.images || [];
 
  return {
    title: product.title,
    openGraph: {
      images: ['/path-to-image.jpg', ...previousImages],
    },
  };
}
 
export default function Page({ params, searchParams }: Props) {}

JSON-LD Schema

JSON-LD is a lightweight data format that helps search engines understand the content on your website. You can put it inside the head tag or the body tag:

 
import Head from "next/head";
 
export default function Page() {
    const jsonLd = {
      "@context": "https://schema.org",
      "@type": "BlogPosting",
      mainEntityOfPage: {
        "@type": "WebPage",
        "@id": "https://startbase.dev"
      },
      headline: "Startbase Studio offers App Development as a Service",
      description: "A tiny development studio offers affordable custom app development subscription services to grow your business. Get a reliable partner with senior  engineers quality at a freelancer cost and say goodbye to the technical headaches.",
      image:
        "https://startbasedev/image.png",
      dateCreated: "2024-06-14T31:35:00+09:00",
      datePublished: "2024-01-11T91:35:00+09:00",
      dateModified: "2024-01-11T91:35:00+09:00",
      author: {
        "@type": "Person",
        name: "Startbase team",
        url: "https://www.linkedin.com/in/startbasedev"
      },
      publisher: {
        "@type": "Person",
        name: "Startbase team",
        logo: {
          "@type": "ImageObject",
          url: "https://startbasedev/logo.jpg"
        }
      },
      inLanguage: "en-US",
      isFamilyFriendly: "true"
    };
 
  return (
    <Head>
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
      />
    </Head>
  );
}

Sitemap

A sitemap helps search engines to efficiently crawl your website and index your URLs. In the App Router, a dynamic sitemap is generated via sitemap.ts, then you can check it at: starbase.dev/sitemap.xml`:

import {
  getAllCategories,
  getAllPostSlugsWithModifyTime,
} from '@/utils/getData';
import { MetadataRoute } from 'next';
 
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const defaultPages = [
    {
      url: 'https://startbase.dev',
      lastModified: new Date(),
      changeFrequency: 'daily',
      priority: 1,
    },
    {
      url: 'https://startbase.dev/blog',
      lastModified: new Date(),
      changeFrequency: 'monthly',
      priority: 0.9,
    },
    {
      url: 'https://startbase.dev/studio',
      lastModified: new Date(),
      changeFrequency: 'monthly',
      priority: 0.9,
    },
  ];
 
  const postSlugs = await getAllPostSlugsWithModifyTime();
  const productSlugs = await getAllCategories();
 
  const sitemap = [
    ...defaultPages,
    ...postSlugs.map((e: any) => ({
      url: `https://startbase.dev/${e.slug}`,
      lastModified: e.modified_at,
      changeFrequency: 'daily',
      priority: 0.8,
    })),
    ...categorySlugs.map((e: any) => ({
      url: `https://startbase.dev/product/${e}`,
      lastModified: new Date(),
      changeFrequency: 'daily',
      priority: 0.7,
    })),
  ];
 
  return sitemap;
}

robots.txt

This file controls which pages search engines should and shouldn’t crawl.

A dynamic robots.ts file can be created to manage this:

import { MetadataRoute } from 'next';
 
export default function robots(): MetadataRoute.Robots {
  return {
    rules: {
      userAgent: '*',
      allow: '/',
      disallow: ['/admin', '/search'],
    },
    sitemap: 'https://startbase.dev/sitemap.xml',
  };
}

Important link tags such as canonical, icon, and apple-touch-icon should be included. For Next.js App Router, the link tags can be defined using the export const metadata or generateMetadata.

export const metadata: Metadata = {
  // add the metadata content we described earlier
  alternates: {
    canonical: 'https://startbase.dev',
  },
};

Script Optimization

Use Next.js <Script> for managing external scripts and optimizing their loading.

import Script from "next/script";
 
<Script
  src="https://example.com/script.js"
  strategy="lazyOnload"
  onLoad={() => console.log("Script loaded successfully")}
/>

If you are using one of these: Google Tag Manager, Google Analytics, Google Maps Embed, YouTube Embed, you can add them via @next/third-parties. First you need to install it:

npm install @next/third-parties

Then you can import what you need from the library like this:

import { GoogleAnalytics } from "@next/third-parties/google";
import Head from "next/head";
 
export default function Page() {
  return (
    <html lang="en" suppressHydrationWarning>
      {process.env.NODE_ENV === "production" && (
        <>
          <GoogleAnalytics gaId="G-XXXXXXXXXX" />
        </>
      )}
    </html>
  );
}

Image Optimization

Better loading times means better SEO. It can contribute your Google PageSpeed score. For image optimization, Next.js provides the next/image component for automatically optimizing and serving images.

import Image from "next/image";
 
<Image src="/image.png" alt="Image description" width={1200} height={630} />

For more information on SEO, refer to the this documentation.